Skip to content

Commit

Permalink
Merge pull request #21 from deriv-com/farabi/grwt-4936/desktop-and-mo…
Browse files Browse the repository at this point in the history
…bile-layout

Farabi/grwt 4936/desktop and mobile layout
  • Loading branch information
farabi-deriv authored Feb 11, 2025
2 parents 93ce743 + 8d294ee commit 16da4ec
Show file tree
Hide file tree
Showing 24 changed files with 509 additions and 323 deletions.
Binary file added public/fall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/rise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 37 additions & 18 deletions src/components/BalanceDisplay/BalanceDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { useClientStore } from '@/stores/clientStore';
import { useOrientationStore } from '@/stores/orientationStore';
import React from "react";
import { useClientStore } from "@/stores/clientStore";
import { useOrientationStore } from "@/stores/orientationStore";

interface BalanceDisplayProps {
onDeposit?: () => void;
Expand All @@ -11,34 +11,53 @@ interface BalanceDisplayProps {

export const BalanceDisplay: React.FC<BalanceDisplayProps> = ({
onDeposit,
depositLabel = 'Deposit',
className = '',
loginUrl = '/login',
depositLabel = "Deposit",
className = "",
loginUrl = "/login",
}) => {
const { isLoggedIn, balance, currency } = useClientStore();
const { isLandscape } = useOrientationStore();

if (!isLoggedIn) {
return (
<div className={`w-full flex items-center justify-end ${className}`}>
<a
href={loginUrl}
className="px-4 py-2 font-bold text-white bg-color-solid-glacier-700 rounded-3xl hover:bg-color-solid-glacier-600"
<>
{!isLandscape && (
<a href="/">
<img
src="/favicon.ico"
alt="Champion Trader Logo"
className="w-8 h-8 rounded-full"
/>
</a>
)}
<div
className={`w-full flex items-center justify-end ${className}`}
>
Log in
</a>
</div>
<a
href={loginUrl}
className="px-4 py-2 font-bold text-white bg-color-solid-glacier-700 rounded-3xl hover:bg-color-solid-glacier-600"
>
Log in
</a>
</div>
</>
);
}

return (
<div className={`flex items-center justify-between ${isLandscape ? 'gap-4' : ''} ${className}`}>
<div
className={`flex items-center justify-between ${
isLandscape ? "gap-4" : ""
} ${className}`}
>
<div className="flex flex-col">
<span className="text-sm text-gray-700">Real</span>
<span className="text-sm font-bold text-teal-500">{balance} {currency}</span>
<span className="text-sm font-medium text-color-solid-glacier-700">Real</span>
<span className="text-sm font-medium ">
{balance} {currency}
</span>
</div>
<button
className="px-4 py-2 font-bold border border-gray-700 rounded-3xl"
<button
className="px-5 py-2 font-medium rounded-3xl bg-color-solid-glacier-700 hover:bg-color-solid-glacier-600"
onClick={onDeposit}
>
{depositLabel}
Expand Down
40 changes: 29 additions & 11 deletions src/components/BottomNav/BottomNav.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { BarChart2, Clock } from "lucide-react";
import { BarChart2, Clock, Menu } from "lucide-react";
import { useNavigate, useLocation } from "react-router-dom";
import { useClientStore } from "@/stores/clientStore";

Expand All @@ -8,27 +8,45 @@ export const BottomNav: React.FC = () => {
const location = useLocation();
const { isLoggedIn } = useClientStore();

if (!isLoggedIn) return null;
const handleMenuClick = () => {
navigate(location.pathname === "/menu" ? "/trade" : "/menu");
};

return (
<nav className="flex items-center justify-around px-4 py-2 border-t bg-white" data-testid="bottom-nav-menu">
<button
onClick={() => navigate('/trade')}
<nav
className="flex items-center justify-around px-4 py-2 border-t bg-white"
data-testid="bottom-nav-menu"
>
<button
onClick={() => navigate("/trade")}
className={`flex flex-col items-center gap-1 ${
location.pathname === '/trade' ? 'text-primary' : 'text-gray-500'
location.pathname === "/trade" ? "text-primary" : "text-gray-500"
}`}
>
<BarChart2 className="w-5 h-5" />
<span className="text-xs">Trade</span>
</button>
<button
onClick={() => navigate('/positions')}
{isLoggedIn && (
<button
onClick={() => navigate("/positions")}
className={`flex flex-col items-center gap-1 ${
location.pathname === "/positions"
? "text-primary"
: "text-gray-500"
}`}
>
<Clock className="w-5 h-5" />
<span className="text-xs">Positions</span>
</button>
)}
<button
onClick={handleMenuClick}
className={`flex flex-col items-center gap-1 ${
location.pathname === '/positions' ? 'text-primary' : 'text-gray-500'
location.pathname === "/menu" ? "text-primary" : "text-gray-500"
}`}
>
<Clock className="w-5 h-5" />
<span className="text-xs">Positions</span>
<Menu className="w-5 h-5" />
<span className="text-xs">Menu</span>
</button>
</nav>
);
Expand Down
6 changes: 0 additions & 6 deletions src/components/BottomNav/__tests__/BottomNav.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ describe('BottomNav', () => {
useClientStore.getState().isLoggedIn = false;
});

it('does not render navigation button when user is logged out', () => {
renderWithRouter();
// Expect that the navigation button with test ID "bottom-nav-menu" is not present.
expect(screen.queryByTestId('bottom-nav-menu')).toBeNull();
});

it('renders navigation button when user is logged in', () => {
useClientStore.getState().isLoggedIn = true;
renderWithRouter();
Expand Down
21 changes: 8 additions & 13 deletions src/components/DurationOptions/DurationOptions.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
import { BarChart2, Clock, Expand } from 'lucide-react';
import { AreaChart } from 'lucide-react';

interface DurationOptionsProps {
className?: string;
}

export const DurationOptions: React.FC<DurationOptionsProps> = ({ className = '' }) => {
return (
<div className={`flex items-center justify-between p-4 border-t border-b ${className}`}>
<div className={`flex items-center p-4 ${className}`}>
<div className="flex items-center gap-4 pr-4">
<button className="text-gray-600 hover:text-gray-700" aria-label="chart">
<AreaChart className="w-5 h-5" />
</button>
<div className='w-0.5 h-5 bg-gray-100'></div>
</div>
<div className="flex items-center gap-4">
<button className="text-sm font-medium text-primary">1t</button>
<button className="text-sm font-medium text-gray-500">1m</button>
<button className="text-sm font-medium text-gray-500">2m</button>
<button className="text-sm font-medium text-gray-500">3m</button>
<button className="text-sm font-medium text-gray-500">5m</button>
</div>
<div className="flex items-center gap-4">
<button className="text-gray-500 hover:text-gray-700" aria-label="chart">
<BarChart2 className="w-5 h-5" />
</button>
<button className="text-gray-500 hover:text-gray-700" aria-label="clock">
<Clock className="w-5 h-5" />
</button>
<button className="text-gray-500 hover:text-gray-700" aria-label="expand">
<Expand className="w-5 h-5" />
</button>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,5 @@ describe('DurationOptions', () => {
render(<DurationOptions />);

expect(screen.getByRole('button', { name: /chart/i })).toBeInTheDocument();
expect(screen.getByRole('button', { name: /clock/i })).toBeInTheDocument();
expect(screen.getByRole('button', { name: /expand/i })).toBeInTheDocument();
});
});
35 changes: 35 additions & 0 deletions src/components/HowToTrade/HowToTrade.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import { useBottomSheetStore } from "@/stores/bottomSheetStore";

export const HowToTrade: React.FC = () => {
const { setBottomSheet } = useBottomSheetStore();

const handleClick = () => {
setBottomSheet(true, "how-to-trade", '800px');
};

return (
<button
onClick={handleClick}
className="text-gray-500 hover:text-gray-600 text-sm flex items-center gap-1"
>
How to trade Rise/Fall?
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-4 h-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.25 4.5l7.5 7.5-7.5 7.5"
/>
</svg>
</button>
);
};

export default HowToTrade;
28 changes: 28 additions & 0 deletions src/components/HowToTrade/__tests__/HowToTrade.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { render, screen, fireEvent } from '@testing-library/react';
import HowToTrade from '../HowToTrade';

const mockSetBottomSheet = jest.fn();

// Mock the bottomSheetStore
jest.mock('@/stores/bottomSheetStore', () => ({
useBottomSheetStore: () => ({
setBottomSheet: mockSetBottomSheet
})
}));

describe('HowToTrade', () => {
beforeEach(() => {
mockSetBottomSheet.mockClear();
});

it('renders correctly', () => {
render(<HowToTrade />);
expect(screen.getByText('How to trade Rise/Fall?')).toBeInTheDocument();
});

it('opens bottom sheet when clicked', () => {
render(<HowToTrade />);
fireEvent.click(screen.getByText('How to trade Rise/Fall?'));
expect(mockSetBottomSheet).toHaveBeenCalledWith(true, 'how-to-trade', '800px');
});
});
1 change: 1 addition & 0 deletions src/components/HowToTrade/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './HowToTrade';
59 changes: 35 additions & 24 deletions src/components/SideNav/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,49 @@ export const SideNav: React.FC = () => {
const { isLandscape } = useOrientationStore();

const handleMenuClick = () => {
navigate(location.pathname === '/menu' ? '/trade' : '/menu');
navigate(location.pathname === "/menu" ? "/trade" : "/menu");
};

return (
<nav className={`${isLandscape ? 'flex' : 'hidden'} flex-col h-[100dvh] sticky top-0 w-16 border-r bg-white overflow-y-auto`}>
<nav
className={`${
isLandscape ? "flex" : "hidden"
} flex-col h-[100dvh] sticky top-0 w-16 border-r bg-white overflow-y-auto`}
>
<div className="flex flex-col items-center gap-6 py-6">
<a href="/" className="pb-4">
<img
src="/logo.png"
alt="Champion Trader Logo"
className="w-8 h-8 rounded-full"
/>
</a>
<button
onClick={() => navigate("/trade")}
className={`flex flex-col items-center gap-1 ${
location.pathname === "/trade" ? "text-primary" : "text-gray-500"
}`}
>
<BarChart2 className="w-5 h-5" />
<span className="text-xs">Trade</span>
</button>
{isLoggedIn && (
<>
<button
onClick={() => navigate('/trade')}
className={`flex flex-col items-center gap-1 ${
location.pathname === '/trade' ? 'text-primary' : 'text-gray-500'
}`}
>
<BarChart2 className="w-5 h-5" />
<span className="text-xs">Trade</span>
</button>
<button
onClick={() => navigate('/positions')}
className={`flex flex-col items-center gap-1 ${
location.pathname === '/positions' ? 'text-primary' : 'text-gray-500'
}`}
>
<Clock className="w-5 h-5" />
<span className="text-xs">Positions</span>
</button>
</>
<button
onClick={() => navigate("/positions")}
className={`flex flex-col items-center gap-1 ${
location.pathname === "/positions"
? "text-primary"
: "text-gray-500"
}`}
>
<Clock className="w-5 h-5" />
<span className="text-xs">Positions</span>
</button>
)}
<button
<button
onClick={handleMenuClick}
className={`flex flex-col items-center gap-1 ${
location.pathname === '/menu' ? 'text-primary' : 'text-gray-500'
location.pathname === "/menu" ? "text-primary" : "text-gray-500"
}`}
>
<Menu className="w-5 h-5" />
Expand Down
Loading

0 comments on commit 16da4ec

Please sign in to comment.