-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
5 changed files
with
229 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import React from "react"; | ||
import { ExternalLink, Home, LogOut, Moon } from "lucide-react"; | ||
import { useLogout } from "@/hooks/useLogout"; | ||
import { useClientStore } from "@/stores/clientStore"; | ||
|
||
export const MenuContent: React.FC = () => { | ||
const [isDarkMode, setIsDarkMode] = React.useState(false); | ||
const { isLoggedIn } = useClientStore(); | ||
const logout = useLogout(); | ||
|
||
return ( | ||
<div className="p-4 space-y-4"> | ||
<a | ||
href="https://champion.trade/" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
className="flex items-center justify-between cursor-pointer py-2" | ||
> | ||
<div className="flex items-center gap-3"> | ||
<Home className="w-5 h-5" /> | ||
<span>Go to Home</span> | ||
</div> | ||
<ExternalLink className="w-5 h-5" /> | ||
</a> | ||
<div className="flex items-center justify-between cursor-pointer py-2"> | ||
<div className="flex items-center gap-3"> | ||
<Moon className="w-5 h-5" /> | ||
<span>Theme</span> | ||
</div> | ||
<label className="relative inline-flex items-center cursor-pointer"> | ||
<input | ||
type="checkbox" | ||
className="sr-only peer" | ||
checked={isDarkMode} | ||
onChange={() => setIsDarkMode(!isDarkMode)} | ||
/> | ||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div> | ||
</label> | ||
</div> | ||
{isLoggedIn && ( | ||
<button | ||
className="flex items-center gap-3 cursor-pointer py-2 w-full hover:bg-gray-100" | ||
onClick={logout} | ||
> | ||
<LogOut className="w-5 h-5" /> | ||
<span>Log out</span> | ||
</button> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default MenuContent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { FC, useState, useEffect } from "react"; | ||
import { useNavigate } from "react-router-dom"; | ||
import { OPEN_POSITIONS, CLOSED_POSITIONS, Position } from "../PositionsSidebar/positionsSidebarStub"; | ||
import { useFilteredPositions } from "../PositionsSidebar/hooks/useFilteredPositions"; | ||
import { FilterDropdown } from "../PositionsSidebar/components/FilterDropdown"; | ||
|
||
export const PositionsContent: FC = () => { | ||
const [isOpenTab, setIsOpenTab] = useState(true); | ||
const navigate = useNavigate(); | ||
const [allPositions, setAllPositions] = useState<Position[]>(OPEN_POSITIONS); | ||
|
||
const { filteredPositions, selectedFilter, handleFilterSelect } = useFilteredPositions({ | ||
isOpenTab, | ||
allPositions, | ||
closedPositions: CLOSED_POSITIONS, | ||
}); | ||
|
||
useEffect(() => { | ||
fetch("/api/positions") | ||
.then(response => response.json()) | ||
.then(data => { | ||
setAllPositions(data); | ||
}) | ||
.catch(error => console.error("Error fetching positions:", error)); | ||
}, []); | ||
|
||
return ( | ||
<div className="flex flex-col h-full"> | ||
<div className="p-6 flex-1 overflow-auto"> | ||
<div className="flex gap-2 p-1 bg-gray-100 rounded-lg"> | ||
<button | ||
className={`flex-1 h-8 flex items-center justify-center rounded-lg transition-all ${ | ||
isOpenTab | ||
? "bg-white text-black shadow-sm" | ||
: "text-gray-500 hover:bg-gray-50" | ||
}`} | ||
onClick={() => setIsOpenTab(true)} | ||
> | ||
Open | ||
</button> | ||
<button | ||
className={`flex-1 h-8 flex items-center justify-center rounded-lg transition-all ${ | ||
!isOpenTab | ||
? "bg-white text-black shadow-sm" | ||
: "text-gray-500 hover:bg-gray-50" | ||
}`} | ||
onClick={() => setIsOpenTab(false)} | ||
> | ||
Closed | ||
</button> | ||
</div> | ||
<div className="mt-4"> | ||
<FilterDropdown | ||
isOpenTab={isOpenTab} | ||
selectedFilter={selectedFilter} | ||
onFilterSelect={handleFilterSelect} | ||
/> | ||
</div> | ||
<div className="mt-4 space-y-4"> | ||
{filteredPositions.map((position) => ( | ||
<div | ||
key={position.id} | ||
className="p-3 rounded-lg shadow-sm cursor-pointer" | ||
onClick={() => navigate(`/contract/${position.id}`)} | ||
> | ||
<div className="flex justify-between text-sm font-medium"> | ||
<div className="flex flex-col items-start"> | ||
<div className="flex items-center gap-2"> | ||
<img src="/market icon.svg" alt="Market Icon" className="w-5 h-8 mb-1" /> | ||
</div> | ||
<span className="mb-[5] font-light text-black-400">{position.type}</span> | ||
<span className="text-s font-light text-gray-500 mb-4">{position.market}</span> | ||
</div> | ||
<div> | ||
<div className="flex flex-col items-end"> | ||
{isOpenTab ? ( | ||
<span className="text-gray-500 w-35 text-xs flex items-center bg-gray-50 px-2 py-1 rounded-md border border-transparent hover:border-gray-300 mb-3"> | ||
<span className="mr-2">⏳</span> {position.ticks} | ||
</span> | ||
) : ( | ||
<span className="text-red-600 bg-red-50 px-2 py-1 rounded-md text-xs font-medium mb-3"> | ||
Closed | ||
</span> | ||
)} | ||
<span className="text-s font-light text-gray-400 mb-[2]">{position.stake}</span> | ||
<span className={`text-sm ${position.profit.startsWith('+') ? 'text-[#008832]' : 'text-red-500'}`}> | ||
{position.profit} | ||
</span> | ||
</div> | ||
</div> | ||
</div> | ||
{isOpenTab && ( | ||
<button className="w-full h-6 flex items-center justify-center py-2 border border-black text-xs font-bold rounded-[8]"> | ||
Close {position.stake} | ||
</button> | ||
)} | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
<div className="p-4 font-bold border-t flex justify-between mt-auto"> | ||
<span className="text-black-300">Total profit/loss: </span> | ||
<span className="text-red-500">-1.50 USD</span> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default PositionsContent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import React, { useEffect, useRef } from "react"; | ||
|
||
interface SidebarProps { | ||
isOpen: boolean; | ||
onClose: () => void; | ||
title: string; | ||
children: React.ReactNode; | ||
} | ||
|
||
export const Sidebar: React.FC<SidebarProps> = ({ isOpen, onClose, title, children }) => { | ||
const sidebarRef = useRef<HTMLDivElement>(null); | ||
|
||
useEffect(() => { | ||
const handleClickOutside = (event: MouseEvent) => { | ||
if (sidebarRef.current && !sidebarRef.current.contains(event.target as Node)) { | ||
onClose(); | ||
} | ||
}; | ||
|
||
document.addEventListener("mousedown", handleClickOutside); | ||
return () => { | ||
document.removeEventListener("mousedown", handleClickOutside); | ||
}; | ||
}, [onClose]); | ||
|
||
return ( | ||
<div | ||
className={`fixed left-[65px] h-full w-[22%] bg-white shadow-lg transform transition-transform duration-300 ease-in-out ${ | ||
isOpen ? "translate-x-0" : "-translate-x-[calc(100%+65px)]" | ||
} z-[51] flex flex-col overflow-hidden`} | ||
ref={sidebarRef} | ||
> | ||
<div className="p-4 border-b flex justify-between items-center"> | ||
<h2 className="text-lg font-bold">{title}</h2> | ||
<button onClick={onClose} className="text-gray-600 hover:text-gray-900">✕</button> | ||
</div> | ||
<div className="flex-1 overflow-auto"> | ||
{children} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Sidebar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { default as Sidebar } from './Sidebar'; | ||
export { default as MenuContent } from './MenuContent'; | ||
export { default as PositionsContent } from './PositionsContent'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters