From f424b3f2b00b5f5c212e7a0e7c03da73520b90bf Mon Sep 17 00:00:00 2001 From: Yuho <yuho@ref.finance> Date: Thu, 28 Dec 2023 20:14:16 +0800 Subject: [PATCH] update dashboard ui --- .prettierignore | 6 +- .prettierrc | 2 +- components/Header/stats/components.tsx | 12 +++- components/Modal/index.tsx | 1 + .../SemiCircleProgressBar.tsx | 2 +- hooks/useUserHealth.ts | 21 ++++++ screens/Dashboard/dashboardOverview.tsx | 71 ++++++++++++++----- styles/global.css | 14 ++++ utils/index.ts | 7 ++ 9 files changed, 113 insertions(+), 23 deletions(-) diff --git a/.prettierignore b/.prettierignore index 19884ef8..1950a93e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,7 @@ LICENSE yarn.lock -tsconfig.tsbuildinfo \ No newline at end of file +tsconfig.tsbuildinfo +.env +.gitignore +.prettierignore +yarn-error.log \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 3bea07cd..7c2413a0 100644 --- a/.prettierrc +++ b/.prettierrc @@ -5,4 +5,4 @@ "printWidth": 100, "useTabs": false, "endOfLine": "auto" -} \ No newline at end of file +} diff --git a/components/Header/stats/components.tsx b/components/Header/stats/components.tsx index 785a9b2a..3fab4fa3 100644 --- a/components/Header/stats/components.tsx +++ b/components/Header/stats/components.tsx @@ -132,20 +132,26 @@ const Label = ({ children, tooltip = "", bgcolor = "rgba(172, 255, 255, 0.1)", . export const StatLabel = ({ title, row, + wrapStyle, + titleClass = "", + titleWrapClass = "", }: { title: { text: string; textStyle?: any; }; + wrapStyle?: any; + titleClass?: string; + titleWrapClass?: string; row?: [{ value: string; icon?: string; valueStyle?: any; valueClass?: string }]; }) => { return ( <div className="flex gap-1 items-start flex-col md:flex-row md:flex-wrap"> <div - className="flex md:items-center gap-2 h6 rounded md:rounded-[21px] bg-dark-100 truncate" - style={{ padding: "3px 6px 5px" }} + className={`flex md:items-center gap-2 h6 rounded md:rounded-[21px] bg-dark-100 truncate ${titleWrapClass}`} + style={wrapStyle || { padding: "3px 6px 5px" }} > - <div style={title?.textStyle} className="h6 text-gray-300"> + <div style={title?.textStyle} className={`h6 text-gray-300 ${titleClass}`}> {title.text} </div> <div className="flex flex-col gap-1 md:flex-row"> diff --git a/components/Modal/index.tsx b/components/Modal/index.tsx index 4753df03..4b8b26d7 100644 --- a/components/Modal/index.tsx +++ b/components/Modal/index.tsx @@ -152,6 +152,7 @@ const Modal = () => { setSelectedCollateralType={setSelectedCollateralType} /> ) : null} + add prop here {action === "Repay" ? ( <CollateralTypeSelectorRepay repayPositions={repayPositions} diff --git a/components/SemiCircleProgressBar/SemiCircleProgressBar.tsx b/components/SemiCircleProgressBar/SemiCircleProgressBar.tsx index 089ce0ee..a920e176 100644 --- a/components/SemiCircleProgressBar/SemiCircleProgressBar.tsx +++ b/components/SemiCircleProgressBar/SemiCircleProgressBar.tsx @@ -27,7 +27,7 @@ const SemiCircleProgressBar = ({ } } // temp - rotateDegree = value + rotateDegree; + rotateDegree = value ? value + rotateDegree : rotateDegree; rotateDegree = Math.min(rotateDegree, MAX_DEGREE); let node; if (children) { diff --git a/hooks/useUserHealth.ts b/hooks/useUserHealth.ts index ec9fc24b..f7cca96d 100644 --- a/hooks/useUserHealth.ts +++ b/hooks/useUserHealth.ts @@ -50,12 +50,33 @@ export function useUserHealth() { ? "Medium" : "Good"; + let allHealths = [ + { + id: `token${healthFactor}`, + type: "Single Token", + healthFactor: Math.floor(healthFactor), + healthStatus: label.toLowerCase(), + }, + ]; + if (LPHealthFactor) { + Object.entries(LPHealthFactor).forEach(([positionId, value]: [string, any]) => { + allHealths.push({ + id: `lp${positionId}`, + type: "LP", + positionId, + ...value, + }); + }); + } + allHealths = allHealths.sort((a, b) => a.healthFactor - b.healthFactor); + return { netAPY, netLiquidityAPY, dailyReturns, healthFactor, LPHealthFactor, + allHealths, lowHealthFactor: LOW_HEALTH_FACTOR, dangerHealthFactor: DANGER_HEALTH_FACTOR, slimStats, diff --git a/screens/Dashboard/dashboardOverview.tsx b/screens/Dashboard/dashboardOverview.tsx index 22ee468c..26d3f9b2 100644 --- a/screens/Dashboard/dashboardOverview.tsx +++ b/screens/Dashboard/dashboardOverview.tsx @@ -25,6 +25,7 @@ const DashboardOverview = ({ suppliedRows, borrowedRows }) => { data: null, }); const userHealth = useUserHealth(); + const [userHealthCur, setUserHealthCur] = useState<any>(); const rewardsObj = useRewards(); const { unreadLiquidation, fetchUnreadLiquidation } = useUnreadLiquidation(); const isMobile = isMobileDevice(); @@ -33,6 +34,12 @@ const DashboardOverview = ({ suppliedRows, borrowedRows }) => { fetchUnreadLiquidation().then(); }, []); + useEffect(() => { + if (userHealth?.allHealths && !userHealthCur?.healthFactor) { + handleHealthClick(userHealth.allHealths[0]); + } + }, [userHealth?.allHealths]); + let totalSuppliedUSD = 0; suppliedRows?.forEach((d) => { const usd = Number(d.supplied) * Number(d.price); @@ -93,6 +100,20 @@ const DashboardOverview = ({ suppliedRows, borrowedRows }) => { ); }); + const handleHealthClick = (o) => { + const valueLocale = o.healthFactor; + setUserHealthCur({ + ...userHealth, + id: o.id, + healthFactor: valueLocale, + data: { + label: o.healthStatus, + valueLabel: `${valueLocale}%`, + valueLocale, + }, + }); + }; + return ( <> <div className="flex gap-2 justify-between items-center mb-4 lg3:hidden"> @@ -176,33 +197,49 @@ const DashboardOverview = ({ suppliedRows, borrowedRows }) => { {recordsButton} </div> - <div className="relative lg3:mr-10 flex flex-col items-center"> - <HealthFactor userHealth={userHealth} /> - {userHealth?.LPHealthFactor ? ( - <div className="lp-healths flex items-center gap-2 mt-4"> - {Object.entries(userHealth.LPHealthFactor).map(([key, value]: [string, any]) => { + <div className="relative flex xsm2:flex-col xsm:items-center items-end gap-4"> + <HealthFactor userHealth={userHealthCur} /> + {userHealth?.allHealths ? ( + <div className="lp-healths flex flex-col items-center gap-2 mt-4"> + {userHealth.allHealths.map((value: any) => { + const isActive = value.id === userHealthCur?.id; const healthColor = { good: "text-primary", warning: "text-warning", danger: "text-red-100", }; - let tokensName = ""; + let tokensName = value?.type; value?.metadata?.tokens?.forEach((d, i) => { const isLast = i === value.metadata.tokens.length - 1; tokensName += `${d.metadata.symbol}${!isLast ? "-" : ""}`; }); return ( - <StatLabel - title={{ text: tokensName || key }} - row={[ - { - value: `${value?.healthFactor}%`, - valueClass: `${healthColor[value.healthStatus]}`, - }, - ]} - key={key} - /> + <div + key={value.id} + className={`cursor-pointer relative health-tab ${ + isActive && "health-tab-active" + }`} + onClick={() => handleHealthClick(value)} + > + {isActive && <div className="arrow-left" />} + <StatLabel + title={{ text: tokensName }} + wrapStyle={{ + background: "none", + border: "1px solid #2E304B", + padding: "7px 8px", + }} + titleWrapClass="w-[158px] rounded-[4px] md:rounded-[4px]" + titleClass="w-[118px] truncate" + row={[ + { + value: `${value?.healthFactor}%`, + valueClass: `${healthColor[value.healthStatus]}`, + }, + ]} + /> + </div> ); })} </div> @@ -265,7 +302,7 @@ const HealthFactor = ({ userHealth }) => { <DangerIcon /> </CustomTooltips> )} - {data.valueLabel} + {data?.valueLabel} </div> <div className="h5 text-gray-300 flex gap-1 items-center justify-center"> Health Factor diff --git a/styles/global.css b/styles/global.css index ce64f80e..b2709744 100644 --- a/styles/global.css +++ b/styles/global.css @@ -777,3 +777,17 @@ options-list::-webkit-scrollbar { user-select: none; /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */ } + +.health-tab:hover, .health-tab-active{ + background: #2E304B; +} + +.health-tab .arrow-left{ + position: absolute; + right:100%; + width: 0; + height: 0; + border-top: 16px solid transparent; + border-bottom: 15px solid transparent; + border-right:10px solid #2E304B; +} diff --git a/utils/index.ts b/utils/index.ts index b63f2610..4490e4cf 100644 --- a/utils/index.ts +++ b/utils/index.ts @@ -227,8 +227,15 @@ export function standardizeAsset(asset) { serializationAsset.symbol = nearMetadata.symbol; serializationAsset.icon = nearMetadata.icon; } + if (serializationAsset.metadata?.symbol === "wNEAR") { + serializationAsset.metadata.symbol = nearMetadata.symbol; + serializationAsset.metadata.icon = nearMetadata.icon; + } if (serializationAsset.symbol === "WOO") { serializationAsset.icon = wooMetadata.icon; } + if (serializationAsset.metadata?.symbol === "WOO") { + serializationAsset.metadata.icon = wooMetadata.icon; + } return serializationAsset; }