Skip to content

Commit

Permalink
Add Margin Trading Details
Browse files Browse the repository at this point in the history
  • Loading branch information
lq0-github committed Feb 29, 2024
1 parent b8d9fda commit aacb61a
Show file tree
Hide file tree
Showing 6 changed files with 444 additions and 39 deletions.
37 changes: 37 additions & 0 deletions screens/Trading/components/ConfirmMobile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useEffect, useState, createContext } from "react";
import { Modal as MUIModal, Typography, Box, Stack, useTheme } from "@mui/material";
import { useAppSelector, useAppDispatch } from "../../../redux/hooks";
import { hideModal, updateAmount, updatePosition } from "../../../redux/appSlice";
import { getModalStatus, getAssetData, getSelectedValues } from "../../../redux/appSelectors";
import { Wrapper } from "../../../components/Modal/style";
import { DEFAULT_POSITION, lpTokenPrefix } from "../../../utils/config";

export const ModalContext = createContext(null) as any;
const ConfirmMobile = () => {
const dispatch = useAppDispatch();
const handleClose = () => dispatch(hideModal());
const theme = useTheme();
const [selectedCollateralType, setSelectedCollateralType] = useState(DEFAULT_POSITION);

return (
<MUIModal open onClose={handleClose}>
<Wrapper
sx={{
"& *::-webkit-scrollbar": {
backgroundColor: theme.custom.scrollbarBg,
},
}}
>
<ModalContext.Provider
value={{
position: selectedCollateralType,
}}
>
<Box sx={{ p: ["20px", "20px"] }}>弹窗内容</Box>
</ModalContext.Provider>
</Wrapper>
</MUIModal>
);
};

export default ConfirmMobile;
72 changes: 72 additions & 0 deletions screens/Trading/components/RangeSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useRef, useState, useEffect } from "react";
import { twMerge } from "tailwind-merge";

const RangeSlider = ({ defaultValue, action }) => {
const allowedValues = [1, 1.25, 1.5, 1.75, 2];
const [value, setValue] = useState(defaultValue);
const [splitList, setSplitList] = useState(allowedValues);
const [matchValue, setMatchValue] = useState(value);
const valueRef = useRef<HTMLInputElement>(null);
const [selectedItem, setSelectedItem] = useState(defaultValue);

useEffect(() => {
if (valueRef.current) {
const nearestValue = allowedValues.reduce((prev, curr) => {
return Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev;
});
const percentage =
((nearestValue - splitList[0]) / (splitList[splitList.length - 1] - splitList[0])) * 100;
valueRef.current.style.backgroundSize = `${percentage}% 100%`;
setMatchValue(nearestValue);
}
}, [value, splitList, allowedValues]);

function changeValue(v) {
const numValue = Number(v);
const nearestValue = allowedValues.reduce((prev, curr) => {
return Math.abs(curr - numValue) < Math.abs(prev - numValue) ? curr : prev;
});
setValue(nearestValue);
setSelectedItem(nearestValue);
}
const actionShowRedColor = action === "Long";
return (
<div className="mt-5 pb-5 border-b border-dark-700 -mx-4 px-4">
<div className="mb-3.5 text-sm text-gray-300">Leverage: {matchValue}X</div>
<div className="relative flex flex-col z-10">
<input
ref={valueRef}
onChange={(e) => changeValue(e.target.value)}
value={value}
type="range"
className={`w-full cursor-pointer ${actionShowRedColor ? "" : "redInput"}`}
style={{ backgroundSize: "100% 100%" }}
min={splitList[0]}
max={splitList[splitList.length - 1]}
step="any"
/>
</div>
<div className={twMerge("flex justify-between items-center mt-2")}>
{splitList.map((p) => (
<div
key={p}
className="flex flex-col items-center cursor-pointer"
onClick={() => changeValue(p)}
>
<span
className={twMerge(
`flex items-center justify-center text-xs text-gray-400 w-11 py-0.5 border border-transparent hover:border-v3LiquidityRemoveBarColor
rounded-lg`,
p === selectedItem && "bg-black bg-opacity-20",
)}
>
{p}X
</span>
</div>
))}
</div>
</div>
);
};

export default RangeSlider;
52 changes: 52 additions & 0 deletions screens/Trading/components/TradingIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,55 @@ export function TokenThinArrow({ ...props }) {
</svg>
);
}

export function TokenSelected({ ...props }) {
return (
<svg
{...props}
width="15"
height="11"
viewBox="0 0 15 11"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M1 3.94737L6.05263 9L14.0526 1" stroke="#D2FF3A" strokeWidth="2" />
</svg>
);
}

export function RefLogoIcon({ ...props }) {
return (
<svg
{...props}
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M7.15625 11.2463H11.2458L7.15625 7.15674V11.2463Z" fill="white" />
<path
d="M11.2461 0.000193119L8.86054 0.00019291L11.2461 2.38574L11.2461 0.000193119Z"
fill="#00C6A2"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7.3275 7.15671C7.27005 7.15671 7.21296 7.15521 7.15625 7.15226V4.59286L9.94058 2.00741C10.3332 2.54314 10.565 3.20408 10.565 3.91918C10.565 5.70722 9.11554 7.15671 7.3275 7.15671ZM9.21348 1.28739L7.15625 3.19768V0.686092C7.21296 0.683137 7.27005 0.681641 7.3275 0.681641C8.03116 0.681641 8.68239 0.906127 9.21348 1.28739Z"
fill="white"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.81714 0.680176H3.75V3.70609L5.12668 5.08277L6.81714 3.51306V0.680176ZM6.81714 4.90824L5.1004 6.50235L3.75 5.15195V11.2448H6.81714V4.90824Z"
fill="white"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3.40793 0.680664H0V5.07017L2.55616 2.51402L3.40793 3.36579V0.680664ZM3.40793 4.81165L2.55616 3.95988L0 6.51603V11.2452H3.40793V4.81165Z"
fill="white"
/>
</svg>
);
}
194 changes: 181 additions & 13 deletions screens/Trading/components/TradingOperate.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,214 @@
import React, { useState } from "react";
import TradingToken from "./tokenbox";
import { SetUp } from "./TradingIcon";
import { RefLogoIcon, SetUp, ShrinkArrow } from "./TradingIcon";
import { useAppDispatch } from "../../../redux/hooks";
import RangeSlider from "./RangeSlider";
import ConfirmMobile from "./ConfirmMobile";

const TradingOperate = () => {
const dispatch = useAppDispatch();
const [activeTab, setActiveTab] = useState("long");

const [showSetUpPopup, setShowSetUpPopup] = useState(false);
const [selectedSetUpOption, setSelectedSetUpOption] = useState("auto");
const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false);
const handleTabClick = (tabString) => {
setActiveTab(tabString);
};

const getTabClassName = (tabName) => {
return activeTab === tabName
? "bg-primary text-dark-200 py-2.5 pl-6 pr-8 rounded-md"
: "text-gray-300 py-2.5 pl-8 pr-10";
};

let timer;
const handleMouseEnter = () => {
clearTimeout(timer);
setShowSetUpPopup(true);
};
const handleMouseLeave = () => {
clearTimeout(timer);
timer = setTimeout(() => {
setShowSetUpPopup(false);
}, 200);
};
const handleSetUpOptionClick = (option) => {
setSelectedSetUpOption(option);
};
const handleConfirmButtonClick = () => {
setIsConfirmModalOpen(true);
};
return (
<div className="w-full pt-4 px-4 pb-9">
<div className="flex justify-between items-center">
<div className="flex bg-dark-200 px-0.5 py-0.5 rounded-md cursor-pointer mr-3">
<div className={getTabClassName("long")} onClick={() => handleTabClick("long")}>
Long NEAR
</div>
<div className={getTabClassName("short")} onClick={() => handleTabClick("short")}>
<div
className={
activeTab === "short"
? "bg-red-50 text-dark-200 py-2.5 pl-6 pr-8 rounded-md"
: getTabClassName("short")
}
onClick={() => handleTabClick("short")}
>
Short NEAR
</div>
</div>
<div>
<div
className="relative z-40 cursor-pointer "
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<SetUp />
{showSetUpPopup && (
<div
onMouseLeave={handleMouseLeave}
className="absolute top-10 right-0 bg-dark-250 border border-dark-500 rounded-md py-6 px-4"
>
<p className="text-base mb-6">Max. Slippage Setting</p>
<div className="flex items-center justify-between h-10">
<div className="bg-dark-200 p-1 rounded-md flex items-center mr-3.5">
<div
className={`py-2 px-5 ${
selectedSetUpOption === "auto" ? "bg-gray-400 rounded " : ""
}`}
onClick={() => handleSetUpOptionClick("auto")}
>
Auto
</div>
<div
className={`py-2 px-5 ${
selectedSetUpOption === "custom" ? "bg-gray-400 rounded " : ""
}`}
onClick={() => handleSetUpOptionClick("custom")}
>
Custom
</div>
</div>
<div className="bg-dark-600 rounded-md py-2.5 px-4 flex items-center justify-between">
<input type="text" value={0.5} style={{ width: "32px" }} />
<div>%</div>
</div>
</div>
</div>
)}
</div>
</div>
<div className="mt-5">
{activeTab === "long" && (
<div className="relative bg-dark-600 border border-dark-500 pt-3 pb-2.5 pr-3 pl-2.5 rounded-md">
<input type="text" value={0} />
<div className="absolute top-2 right-2">
<TradingToken />
<>
<div className="relative bg-dark-600 border border-dark-500 pt-3 pb-2.5 pr-3 pl-2.5 rounded-md z-30">
<input type="text" value={0} />
<div className="absolute top-2 right-2">
<TradingToken />
</div>
<p className="text-gray-300 mt-2 text-xs">Use: $0.00</p>
</div>
<p className="text-gray-300 mt-2 text-xs">Use: $0.00</p>
</div>
<div className="relative my-2.5 flex justify-end z-0 w-1/2" style={{ zoom: "2" }}>
<ShrinkArrow />
</div>
<div className="relative bg-dark-600 border border-dark-500 pt-3 pb-2.5 pr-3 pl-2.5 rounded-md z-20">
<input type="text" value={0} />
<div className="absolute top-2 right-2">
<TradingToken />
</div>
<p className="text-gray-300 mt-2 text-xs">Long: $0.00</p>
</div>
<RangeSlider defaultValue={1.5} action="Long" />
<div className="mt-5">
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Position Size</div>
<div>
45.2435 NEAR
<span className="text-xs text-gray-300 ml-1.5">($149.35)</span>
</div>
</div>
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Liq. Price</div>
<div>$1.23</div>
</div>
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Fee</div>
<div className="flex items-center justify-center">
<p className="border-b border-dashed border-dark-800">0.26</p>
NEAR
<span className="text-xs text-gray-300 ml-1.5">($0.89)</span>
</div>
</div>
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Route</div>
<div className="flex items-center justify-center">
<div className="border-r mr-1.5 pr-1.5 border-dark-800">
<RefLogoIcon />
</div>
NEAR &gt; USDT.e &gt; USDC.e
</div>
</div>
<div
className="flex items-center justify-between bg-primary text-dark-200 text-base rounded-md h-12 text-center cursor-pointer"
onClick={handleConfirmButtonClick}
>
<div className="flex-grow">Long NEAR 1.5x</div>
</div>
{isConfirmModalOpen && <ConfirmMobile />}
</div>
</>
)}
{activeTab === "short" && (
<>
<div className="relative bg-dark-600 border border-dark-500 pt-3 pb-2.5 pr-3 pl-2.5 rounded-md z-30">
<input type="text" value={0} />
<div className="absolute top-2 right-2">
<TradingToken />
</div>
<p className="text-gray-300 mt-2 text-xs">Use: $0.00</p>
</div>
<div className="relative my-2.5 flex justify-end z-0 w-1/2" style={{ zoom: "2" }}>
<ShrinkArrow />
</div>
<div className="relative bg-dark-600 border border-dark-500 pt-3 pb-2.5 pr-3 pl-2.5 rounded-md z-20">
<input type="text" value={0} />
<div className="absolute top-2 right-2">
<TradingToken />
</div>
<p className="text-gray-300 mt-2 text-xs">Long: $0.00</p>
</div>
<RangeSlider defaultValue={1.75} action="Short" />
<div className="mt-5">
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Position Size</div>
<div>
45.2435 NEAR
<span className="text-xs text-gray-300 ml-1.5">($149.35)</span>
</div>
</div>
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Liq. Price</div>
<div>$1.23</div>
</div>
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Fee</div>
<div className="flex items-center justify-center">
<p className="border-b border-dashed border-dark-800">0.26</p>
NEAR
<span className="text-xs text-gray-300 ml-1.5">($0.89)</span>
</div>
</div>
<div className="flex items-center justify-between text-sm mb-4">
<div className="text-gray-300">Route</div>
<div className="flex items-center justify-center">
<div className="border-r mr-1.5 pr-1.5 border-dark-800">
<RefLogoIcon />
</div>
NEAR &gt; USDT.e &gt; USDC.e
</div>
</div>
<div className="flex items-center justify-between bg-red-50 text-dark-200 text-base rounded-md h-12 text-center cursor-pointer">
<div className="flex-grow">Long NEAR 1.5x</div>
</div>
</div>
</>
)}
{activeTab === "short" && <p>Content for Short NEAR</p>}
</div>
</div>
);
Expand Down
Loading

0 comments on commit aacb61a

Please sign in to comment.