Merge pull request #12 from blockworks-foundation/onboarding-tour
add onboarding ui tour
This commit is contained in:
commit
b3f46655a7
|
@ -8,7 +8,12 @@ import BottomBar from './mobile/BottomBar'
|
||||||
import BounceLoader from './shared/BounceLoader'
|
import BounceLoader from './shared/BounceLoader'
|
||||||
import TopBar from './TopBar'
|
import TopBar from './TopBar'
|
||||||
import useLocalStorageState from '../hooks/useLocalStorageState'
|
import useLocalStorageState from '../hooks/useLocalStorageState'
|
||||||
import { SIDEBAR_COLLAPSE_KEY } from '../utils/constants'
|
import {
|
||||||
|
IS_ONBOARDED_KEY,
|
||||||
|
ONBOARDING_TOUR_KEY,
|
||||||
|
SIDEBAR_COLLAPSE_KEY,
|
||||||
|
} from '../utils/constants'
|
||||||
|
import OnboardingTour from './OnboardingTour'
|
||||||
|
|
||||||
const Layout = ({ children }: { children: ReactNode }) => {
|
const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
const connected = mangoStore((s) => s.connected)
|
const connected = mangoStore((s) => s.connected)
|
||||||
|
@ -17,6 +22,8 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
SIDEBAR_COLLAPSE_KEY,
|
SIDEBAR_COLLAPSE_KEY,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
const [showOnboardingTour] = useLocalStorageState(ONBOARDING_TOUR_KEY, false)
|
||||||
|
const [isOnboarded] = useLocalStorageState(IS_ONBOARDED_KEY)
|
||||||
const { width } = useViewport()
|
const { width } = useViewport()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -77,6 +84,9 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{showOnboardingTour && isOnboarded && connected ? (
|
||||||
|
<OnboardingTour />
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,16 @@ import { useLocalStorageStringState } from '../hooks/useLocalStorageState'
|
||||||
import { LAST_ACCOUNT_KEY } from '../utils/constants'
|
import { LAST_ACCOUNT_KEY } from '../utils/constants'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import { retryFn } from '../utils'
|
import { retryFn } from '../utils'
|
||||||
|
import Loading from './shared/Loading'
|
||||||
|
|
||||||
const MangoAccountsList = ({
|
const MangoAccountsList = ({
|
||||||
mangoAccount,
|
mangoAccount,
|
||||||
}: {
|
}: {
|
||||||
mangoAccount: MangoAccount
|
mangoAccount: MangoAccount | undefined
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
const mangoAccounts = mangoStore((s) => s.mangoAccounts.accounts)
|
const mangoAccounts = mangoStore((s) => s.mangoAccounts.accounts)
|
||||||
|
const loading = mangoStore((s) => s.mangoAccount.initialLoad)
|
||||||
const [showNewAccountModal, setShowNewAccountModal] = useState(false)
|
const [showNewAccountModal, setShowNewAccountModal] = useState(false)
|
||||||
const [, setLastAccountViewed] = useLocalStorageStringState(LAST_ACCOUNT_KEY)
|
const [, setLastAccountViewed] = useLocalStorageStringState(LAST_ACCOUNT_KEY)
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ const MangoAccountsList = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div id="step-one">
|
||||||
<Popover>
|
<Popover>
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
|
@ -53,7 +55,7 @@ const MangoAccountsList = ({
|
||||||
<div className="mr-2">
|
<div className="mr-2">
|
||||||
<p className="text-right text-xs">{t('accounts')}</p>
|
<p className="text-right text-xs">{t('accounts')}</p>
|
||||||
<p className="text-left text-sm font-bold text-th-fgd-1">
|
<p className="text-left text-sm font-bold text-th-fgd-1">
|
||||||
{mangoAccount.name}
|
{mangoAccount ? mangoAccount.name : 'No Accounts'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
|
@ -75,7 +77,9 @@ const MangoAccountsList = ({
|
||||||
leaveTo="opacity-0"
|
leaveTo="opacity-0"
|
||||||
>
|
>
|
||||||
<Popover.Panel className="absolute top-[13.5px] -right-5 z-10 mr-4 w-56 rounded-md rounded-t-none border border-th-bkg-3 bg-th-bkg-1 p-4">
|
<Popover.Panel className="absolute top-[13.5px] -right-5 z-10 mr-4 w-56 rounded-md rounded-t-none border border-th-bkg-3 bg-th-bkg-1 p-4">
|
||||||
{mangoAccounts.length ? (
|
{loading ? (
|
||||||
|
<Loading />
|
||||||
|
) : mangoAccounts.length ? (
|
||||||
mangoAccounts.map((acc) => (
|
mangoAccounts.map((acc) => (
|
||||||
<div key={acc.publicKey.toString()}>
|
<div key={acc.publicKey.toString()}>
|
||||||
<button
|
<button
|
||||||
|
@ -84,14 +88,16 @@ const MangoAccountsList = ({
|
||||||
>
|
>
|
||||||
{acc.name}
|
{acc.name}
|
||||||
{acc.publicKey.toString() ===
|
{acc.publicKey.toString() ===
|
||||||
mangoAccount.publicKey.toString() ? (
|
mangoAccount!.publicKey.toString() ? (
|
||||||
<CheckCircleIcon className="h-5 w-5 text-th-green" />
|
<CheckCircleIcon className="h-5 w-5 text-th-green" />
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<p>Loading...</p>
|
<p className="mb-4 text-center text-sm">
|
||||||
|
Create your first account 😎
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<LinkButton
|
<LinkButton
|
||||||
|
@ -114,7 +120,7 @@ const MangoAccountsList = ({
|
||||||
onClose={() => setShowNewAccountModal(false)}
|
onClose={() => setShowNewAccountModal(false)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import {
|
||||||
|
CardinalOrientation,
|
||||||
|
MaskOptions,
|
||||||
|
Walktour,
|
||||||
|
WalktourLogic,
|
||||||
|
} from 'walktour'
|
||||||
|
import useLocalStorageState from '../hooks/useLocalStorageState'
|
||||||
|
import { ONBOARDING_TOUR_KEY } from '../utils/constants'
|
||||||
|
|
||||||
|
const OnboardingTour = () => {
|
||||||
|
const [, setShowOnboardingTour] = useLocalStorageState(ONBOARDING_TOUR_KEY)
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const renderTooltip = (tourLogic: WalktourLogic | undefined) => {
|
||||||
|
const { title, description } = tourLogic!.stepContent
|
||||||
|
const { next, prev, close, allSteps, stepIndex } = tourLogic!
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setShowOnboardingTour(false)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative w-72 rounded-lg bg-gradient-to-b from-gradient-start via-gradient-mid to-gradient-end p-4">
|
||||||
|
<button
|
||||||
|
onClick={handleClose}
|
||||||
|
className={`absolute right-4 top-4 z-50 text-th-bkg-3 focus:outline-none md:right-2 md:top-2 md:hover:text-th-primary`}
|
||||||
|
>
|
||||||
|
<XMarkIcon className={`h-5 w-5`} />
|
||||||
|
</button>
|
||||||
|
<h3 className="text-th-bkg-1">{title}</h3>
|
||||||
|
<p className="text-sm text-th-bkg-1">{description}</p>
|
||||||
|
<div className="mt-4 flex items-center justify-between">
|
||||||
|
{stepIndex !== 0 ? (
|
||||||
|
<button
|
||||||
|
className="default-transition h-8 rounded-md border border-th-bkg-1 px-3 font-bold text-th-bkg-1 focus:outline-none md:hover:border-th-bkg-3 md:hover:text-th-bkg-3"
|
||||||
|
onClick={() => prev()}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<div className="h-8 w-[58.25px]" />
|
||||||
|
)}
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
{allSteps.map((s, i) => (
|
||||||
|
<div
|
||||||
|
className={`h-1 w-1 rounded-full ${
|
||||||
|
i === stepIndex ? 'bg-th-primary' : 'bg-[rgba(0,0,0,0.2)]'
|
||||||
|
}`}
|
||||||
|
key={s.title}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{stepIndex !== allSteps.length - 1 ? (
|
||||||
|
<button
|
||||||
|
className="default-transition h-8 rounded-md bg-th-bkg-1 px-3 font-bold text-th-fgd-1 focus:outline-none md:hover:bg-th-bkg-3"
|
||||||
|
onClick={() => next()}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
className="default-transition h-8 rounded-md bg-th-bkg-1 px-3 font-bold text-th-fgd-1 focus:outline-none md:hover:bg-th-bkg-3"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
Finish
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
selector: '#step-one',
|
||||||
|
title: 'Your Accounts',
|
||||||
|
description:
|
||||||
|
'Switch between accounts and create new ones. Use multiple accounts to trade isolated margin and protect your capital from liquidation.',
|
||||||
|
orientationPreferences: [CardinalOrientation.SOUTHEAST],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-two',
|
||||||
|
title: 'Account Value',
|
||||||
|
description:
|
||||||
|
'The value of your assets (deposits) minus the value of your liabilities (borrows).',
|
||||||
|
orientationPreferences: [CardinalOrientation.EASTNORTH],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-three',
|
||||||
|
title: 'Health',
|
||||||
|
description:
|
||||||
|
'If your account health reaches 0% your account will be liquidated. You can increase the health of your account by making a deposit.',
|
||||||
|
orientationPreferences: [CardinalOrientation.SOUTHWEST],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-four',
|
||||||
|
title: 'Free Collateral',
|
||||||
|
description:
|
||||||
|
"The amount of capital you have to trade or borrow against. When your free collateral reaches $0 you won't be able to make withdrawals.",
|
||||||
|
orientationPreferences: [CardinalOrientation.SOUTHWEST],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-five',
|
||||||
|
title: 'Total Interest Value',
|
||||||
|
description:
|
||||||
|
'The value of interest earned (deposits) minus interest paid (borrows).',
|
||||||
|
orientationPreferences: [CardinalOrientation.SOUTHWEST],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-six',
|
||||||
|
title: 'Health Check',
|
||||||
|
description:
|
||||||
|
'Check the health of your account from any screen in the app. A green heart represents good health, orange okay and red poor.',
|
||||||
|
orientationPreferences: [CardinalOrientation.EASTSOUTH],
|
||||||
|
movingTarget: true,
|
||||||
|
customNextFunc: (tourLogic: WalktourLogic) => {
|
||||||
|
router.push('/trade')
|
||||||
|
setTimeout(() => tourLogic.next(), 1000)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-seven',
|
||||||
|
title: 'Trade',
|
||||||
|
description:
|
||||||
|
"You choose the quote token of your trades. This means you can easily trade tokens on their relative strength vs. another token. Let's say your thesis is BTC will see diminishing returns relative to SOL. You can sell BTC and buy SOL. Now you are long SOL/BTC",
|
||||||
|
orientationPreferences: [CardinalOrientation.CENTER],
|
||||||
|
customPrevFunc: (tourLogic: WalktourLogic) => {
|
||||||
|
router.push('/')
|
||||||
|
tourLogic.prev()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-eight',
|
||||||
|
title: 'Trade Settings',
|
||||||
|
description:
|
||||||
|
'Edit your slippage settings and toggle margin on and off. When margin is off your trades will be limited by your balance for each token.',
|
||||||
|
orientationPreferences: [CardinalOrientation.WESTNORTH],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-nine',
|
||||||
|
title: 'Token to Sell',
|
||||||
|
description:
|
||||||
|
'Select the token you want to sell. If your sell size is above your token balance a loan will be opened to cover the shortfall.',
|
||||||
|
orientationPreferences: [CardinalOrientation.WESTNORTH],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: '#step-ten',
|
||||||
|
title: 'Health Impact',
|
||||||
|
description:
|
||||||
|
'Projects the health of your account before you make a trade.',
|
||||||
|
orientationPreferences: [CardinalOrientation.WESTNORTH],
|
||||||
|
movingTarget: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Walktour
|
||||||
|
customTooltipRenderer={renderTooltip}
|
||||||
|
steps={steps}
|
||||||
|
updateInterval={200}
|
||||||
|
disableCloseOnClick
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OnboardingTour
|
|
@ -9,6 +9,7 @@ import {
|
||||||
CurrencyDollarIcon,
|
CurrencyDollarIcon,
|
||||||
ChartBarIcon,
|
ChartBarIcon,
|
||||||
Cog8ToothIcon,
|
Cog8ToothIcon,
|
||||||
|
InformationCircleIcon,
|
||||||
ArrowsRightLeftIcon,
|
ArrowsRightLeftIcon,
|
||||||
} from '@heroicons/react/20/solid'
|
} from '@heroicons/react/20/solid'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
@ -17,12 +18,26 @@ import { Fragment, ReactNode, useEffect, useState } from 'react'
|
||||||
import { Disclosure, Popover, Transition } from '@headlessui/react'
|
import { Disclosure, Popover, Transition } from '@headlessui/react'
|
||||||
import MangoAccountSummary from './account/MangoAccountSummary'
|
import MangoAccountSummary from './account/MangoAccountSummary'
|
||||||
import Tooltip from './shared/Tooltip'
|
import Tooltip from './shared/Tooltip'
|
||||||
|
import { HealthType } from '@blockworks-foundation/mango-v4'
|
||||||
|
import { useWallet } from '@solana/wallet-adapter-react'
|
||||||
|
import useLocalStorageState from '../hooks/useLocalStorageState'
|
||||||
|
import { ONBOARDING_TOUR_KEY } from '../utils/constants'
|
||||||
|
|
||||||
const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
||||||
|
const [, setShowOnboardingTour] = useLocalStorageState(ONBOARDING_TOUR_KEY)
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
|
const { connected } = useWallet()
|
||||||
|
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { pathname } = router
|
const { pathname } = router
|
||||||
|
|
||||||
|
const handleTakeTour = () => {
|
||||||
|
if (pathname !== '/') {
|
||||||
|
router.push('/')
|
||||||
|
}
|
||||||
|
setShowOnboardingTour(true)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col justify-between transition-all duration-500 ${
|
className={`flex flex-col justify-between transition-all duration-500 ${
|
||||||
|
@ -126,10 +141,51 @@ const SideNav = ({ collapsed }: { collapsed: boolean }) => {
|
||||||
isExternal
|
isExternal
|
||||||
showTooltip={false}
|
showTooltip={false}
|
||||||
/>
|
/>
|
||||||
|
{connected ? (
|
||||||
|
<button
|
||||||
|
className="default-transition mt-1 flex items-center px-4 text-th-fgd-2 md:hover:text-th-primary"
|
||||||
|
onClick={handleTakeTour}
|
||||||
|
>
|
||||||
|
<InformationCircleIcon className="mr-3 h-5 w-5" />
|
||||||
|
<span className="text-base">Take UI Tour</span>
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
</ExpandableMenuItem>
|
</ExpandableMenuItem>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MangoAccountSummary collapsed={collapsed} />
|
<div className="border-t border-th-bkg-3">
|
||||||
|
<ExpandableMenuItem
|
||||||
|
collapsed={collapsed}
|
||||||
|
icon={
|
||||||
|
<HealthHeart
|
||||||
|
health={
|
||||||
|
mangoAccount
|
||||||
|
? mangoAccount.getHealthRatioUi(HealthType.maint)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
size={32}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
<div className="text-left">
|
||||||
|
<p className="mb-0.5 whitespace-nowrap text-xs">Health Check</p>
|
||||||
|
<p className="whitespace-nowrap text-sm font-bold text-th-fgd-1">
|
||||||
|
{mangoAccount
|
||||||
|
? mangoAccount.name
|
||||||
|
: connected
|
||||||
|
? 'No Account'
|
||||||
|
: 'Connect'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
alignBottom
|
||||||
|
hideIconBg
|
||||||
|
>
|
||||||
|
<div className="px-4 pb-4 pt-2">
|
||||||
|
<MangoAccountSummary />
|
||||||
|
</div>
|
||||||
|
</ExpandableMenuItem>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,7 @@ const TopBar = () => {
|
||||||
</span>
|
</span>
|
||||||
{connected ? (
|
{connected ? (
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
{mangoAccount ? (
|
<MangoAccountsList mangoAccount={mangoAccount} />
|
||||||
<MangoAccountsList mangoAccount={mangoAccount} />
|
|
||||||
) : null}
|
|
||||||
<ConnectedMenu />
|
<ConnectedMenu />
|
||||||
</div>
|
</div>
|
||||||
) : isOnboarded ? (
|
) : isOnboarded ? (
|
||||||
|
|
|
@ -130,14 +130,14 @@ const AccountPage = () => {
|
||||||
}, [totalInterestData])
|
}, [totalInterestData])
|
||||||
|
|
||||||
const maintHealth = useMemo(() => {
|
const maintHealth = useMemo(() => {
|
||||||
return mangoAccount ? mangoAccount.getHealthRatioUi(HealthType.maint) : 100
|
return mangoAccount ? mangoAccount.getHealthRatioUi(HealthType.maint) : 0
|
||||||
}, [mangoAccount])
|
}, [mangoAccount])
|
||||||
|
|
||||||
return !chartToShow ? (
|
return !chartToShow ? (
|
||||||
<>
|
<>
|
||||||
<div className="mb-8 flex flex-col md:mb-10 lg:flex-row lg:items-end lg:justify-between">
|
<div className="mb-8 flex flex-col md:mb-10 lg:flex-row lg:items-end lg:justify-between">
|
||||||
<div className="mb-4 flex items-center space-x-6 lg:mb-0">
|
<div className="mb-4 flex items-center space-x-6 lg:mb-0">
|
||||||
<div>
|
<div id="step-two">
|
||||||
<p className="mb-1.5">{t('account-value')}</p>
|
<p className="mb-1.5">{t('account-value')}</p>
|
||||||
<div className="mb-1 flex items-center text-5xl font-bold text-th-fgd-1">
|
<div className="mb-1 flex items-center text-5xl font-bold text-th-fgd-1">
|
||||||
$
|
$
|
||||||
|
@ -221,21 +221,25 @@ const AccountPage = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-3 gap-x-6 border-b border-th-bkg-3 md:border-b-0">
|
<div className="grid grid-cols-3 gap-x-6 border-b border-th-bkg-3 md:border-b-0">
|
||||||
<div className="col-span-3 border-t border-th-bkg-3 py-4 md:col-span-1 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
<div className="col-span-3 border-t border-th-bkg-3 py-4 md:col-span-1 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
||||||
<p className="text-th-fgd-3">{t('health')}</p>
|
<div id="step-three">
|
||||||
<p className="text-2xl font-bold text-th-fgd-1">{maintHealth}%</p>
|
<p className="text-th-fgd-3">{t('health')}</p>
|
||||||
|
<p className="text-2xl font-bold text-th-fgd-1">{maintHealth}%</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-3 border-t border-th-bkg-3 py-4 md:col-span-1 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
<div className="col-span-3 border-t border-th-bkg-3 py-4 md:col-span-1 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
||||||
<p className="text-th-fgd-3">{t('free-collateral')}</p>
|
<div id="step-four">
|
||||||
<p className="text-2xl font-bold text-th-fgd-1">
|
<p className="text-th-fgd-3">{t('free-collateral')}</p>
|
||||||
{mangoAccount
|
<p className="text-2xl font-bold text-th-fgd-1">
|
||||||
? formatFixedDecimals(
|
{mangoAccount
|
||||||
toUiDecimalsForQuote(
|
? formatFixedDecimals(
|
||||||
mangoAccount.getCollateralValue()!.toNumber()
|
toUiDecimalsForQuote(
|
||||||
),
|
mangoAccount.getCollateralValue()!.toNumber()
|
||||||
true
|
),
|
||||||
)
|
true
|
||||||
: (0).toFixed(2)}
|
)
|
||||||
</p>
|
: (0).toFixed(2)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="col-span-4 flex items-center justify-between border-t border-th-bkg-3 py-4 md:col-span-2 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
{/* <div className="col-span-4 flex items-center justify-between border-t border-th-bkg-3 py-4 md:col-span-2 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
||||||
<div>
|
<div>
|
||||||
|
@ -254,7 +258,7 @@ const AccountPage = () => {
|
||||||
) : null}
|
) : null}
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className="col-span-3 flex items-center justify-between border-t border-th-bkg-3 py-4 md:col-span-1 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
<div className="col-span-3 flex items-center justify-between border-t border-th-bkg-3 py-4 md:col-span-1 md:border-l md:border-t-0 md:pl-6 lg:col-span-1">
|
||||||
<div>
|
<div id="step-five">
|
||||||
<p className="text-th-fgd-3">{t('total-interest-value')}</p>
|
<p className="text-th-fgd-3">{t('total-interest-value')}</p>
|
||||||
<p className="text-2xl font-bold text-th-fgd-1">
|
<p className="text-2xl font-bold text-th-fgd-1">
|
||||||
{formatFixedDecimals(interestTotalValue, true)}
|
{formatFixedDecimals(interestTotalValue, true)}
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
const HealthHeart = ({ health, size }: { health: number; size: number }) => {
|
const HealthHeart = ({
|
||||||
|
health,
|
||||||
|
size,
|
||||||
|
}: {
|
||||||
|
health: number | undefined
|
||||||
|
size: number
|
||||||
|
}) => {
|
||||||
const styles = {
|
const styles = {
|
||||||
height: `${size}px`,
|
height: `${size}px`,
|
||||||
width: `${size}px`,
|
width: `${size}px`,
|
||||||
|
@ -6,13 +12,16 @@ const HealthHeart = ({ health, size }: { health: number; size: number }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
id="step-six"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
className={
|
className={
|
||||||
health > 15 && health < 50
|
health
|
||||||
? 'text-th-orange'
|
? health > 15 && health < 50
|
||||||
: health >= 50
|
? 'text-th-orange'
|
||||||
? 'text-th-green'
|
: health >= 50
|
||||||
: 'text-th-red'
|
? 'text-th-green'
|
||||||
|
: 'text-th-red'
|
||||||
|
: 'text-th-fgd-4'
|
||||||
}
|
}
|
||||||
style={styles}
|
style={styles}
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
|
@ -30,7 +39,13 @@ const HealthHeart = ({ health, size }: { health: number; size: number }) => {
|
||||||
keyTimes="0;0.5;1"
|
keyTimes="0;0.5;1"
|
||||||
values="1;1.1;1"
|
values="1;1.1;1"
|
||||||
dur={
|
dur={
|
||||||
health > 15 && health < 50 ? '1s' : health >= 50 ? '2s' : '0.33s'
|
health
|
||||||
|
? health > 15 && health < 50
|
||||||
|
? '1s'
|
||||||
|
: health >= 50
|
||||||
|
? '2s'
|
||||||
|
: '0.33s'
|
||||||
|
: '0s'
|
||||||
}
|
}
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
@ -38,7 +53,13 @@ const HealthHeart = ({ health, size }: { health: number; size: number }) => {
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
values="0.8;1;0.8"
|
values="0.8;1;0.8"
|
||||||
dur={
|
dur={
|
||||||
health > 15 && health < 50 ? '1s' : health >= 50 ? '2s' : '0.33s'
|
health
|
||||||
|
? health > 15 && health < 50
|
||||||
|
? '1s'
|
||||||
|
: health >= 50
|
||||||
|
? '2s'
|
||||||
|
: '0.33s'
|
||||||
|
: '0s'
|
||||||
}
|
}
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,89 +10,64 @@ import DepositModal from '../modals/DepositModal'
|
||||||
import WithdrawModal from '../modals/WithdrawModal'
|
import WithdrawModal from '../modals/WithdrawModal'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import { ArrowDownTrayIcon } from '@heroicons/react/20/solid'
|
import { ArrowDownTrayIcon } from '@heroicons/react/20/solid'
|
||||||
|
import { useWallet } from '@solana/wallet-adapter-react'
|
||||||
import HealthHeart from './HealthHeart'
|
import HealthHeart from './HealthHeart'
|
||||||
import { ExpandableMenuItem } from '../SideNav'
|
import { ExpandableMenuItem } from '../SideNav'
|
||||||
|
|
||||||
const MangoAccountSummary = ({ collapsed }: { collapsed: boolean }) => {
|
const MangoAccountSummary = ({ collapsed }: { collapsed: boolean }) => {
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
|
const { connected } = useWallet()
|
||||||
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
|
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
|
||||||
const [showDepositModal, setShowDepositModal] = useState(false)
|
const [showDepositModal, setShowDepositModal] = useState(false)
|
||||||
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
|
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{mangoAccount ? (
|
<div className="mb-4 space-y-2">
|
||||||
<div className="border-t border-th-bkg-3">
|
<div>
|
||||||
<ExpandableMenuItem
|
<p className="text-sm text-th-fgd-3">{t('health')}</p>
|
||||||
collapsed={collapsed}
|
<p className="text-sm font-bold text-th-fgd-1">
|
||||||
icon={
|
{mangoAccount ? mangoAccount.getHealthRatioUi(HealthType.maint) : 0}
|
||||||
<HealthHeart
|
%
|
||||||
health={mangoAccount.getHealthRatioUi(HealthType.maint)!}
|
</p>
|
||||||
size={32}
|
</div>
|
||||||
/>
|
<div>
|
||||||
}
|
<p className="text-sm text-th-fgd-3">{t('account-value')}</p>
|
||||||
title={
|
<p className="text-sm font-bold text-th-fgd-1">
|
||||||
<div className="text-left">
|
$
|
||||||
<p className="mb-0.5 whitespace-nowrap text-xs">Health Check</p>
|
{mangoAccount
|
||||||
<p className="text-sm font-bold text-th-fgd-1">
|
? formatDecimal(
|
||||||
{mangoAccount.name}
|
toUiDecimalsForQuote(mangoAccount.getEquity()!.toNumber()),
|
||||||
</p>
|
2
|
||||||
</div>
|
)
|
||||||
}
|
: (0).toFixed(2)}
|
||||||
alignBottom
|
</p>
|
||||||
hideIconBg
|
</div>
|
||||||
>
|
<div>
|
||||||
<div className="px-4 pb-4 pt-2">
|
<p className="text-sm text-th-fgd-3">{t('free-collateral')}</p>
|
||||||
<div className="mb-4 space-y-2">
|
<p className="text-sm font-bold text-th-fgd-1">
|
||||||
<div>
|
$
|
||||||
<p className="text-sm text-th-fgd-3">{t('health')}</p>
|
{mangoAccount
|
||||||
<p className="text-sm font-bold text-th-fgd-1">
|
? formatDecimal(
|
||||||
{mangoAccount
|
toUiDecimalsForQuote(
|
||||||
? mangoAccount.getHealthRatioUi(HealthType.maint)
|
mangoAccount.getCollateralValue()!.toNumber()
|
||||||
: 100}
|
),
|
||||||
%
|
2
|
||||||
</p>
|
)
|
||||||
</div>
|
: (0).toFixed(2)}
|
||||||
<div>
|
</p>
|
||||||
<p className="text-sm text-th-fgd-3">{t('account-value')}</p>
|
</div>
|
||||||
<p className="text-sm font-bold text-th-fgd-1">
|
</div>
|
||||||
$
|
<div className="space-y-2">
|
||||||
{mangoAccount
|
<Button
|
||||||
? formatDecimal(
|
className="flex w-full items-center justify-center"
|
||||||
toUiDecimalsForQuote(
|
disabled={!mangoAccount || !connected}
|
||||||
mangoAccount.getEquity()!.toNumber()
|
onClick={() => setShowDepositModal(true)}
|
||||||
),
|
>
|
||||||
2
|
<ArrowDownTrayIcon className="mr-2 h-5 w-5" />
|
||||||
)
|
{t('deposit')}
|
||||||
: (0).toFixed(2)}
|
</Button>
|
||||||
</p>
|
{/* <Button
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-th-fgd-3">
|
|
||||||
{t('free-collateral')}
|
|
||||||
</p>
|
|
||||||
<p className="text-sm font-bold text-th-fgd-1">
|
|
||||||
$
|
|
||||||
{mangoAccount
|
|
||||||
? formatDecimal(
|
|
||||||
toUiDecimalsForQuote(
|
|
||||||
mangoAccount.getCollateralValue()!.toNumber()
|
|
||||||
),
|
|
||||||
2
|
|
||||||
)
|
|
||||||
: (0).toFixed(2)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Button
|
|
||||||
className="flex w-full items-center justify-center"
|
|
||||||
onClick={() => setShowDepositModal(true)}
|
|
||||||
>
|
|
||||||
<ArrowDownTrayIcon className="mr-2 h-5 w-5" />
|
|
||||||
{t('deposit')}
|
|
||||||
</Button>
|
|
||||||
{/* <Button
|
|
||||||
className="w-full"
|
className="w-full"
|
||||||
onClick={() => setShowWithdrawModal(true)}
|
onClick={() => setShowWithdrawModal(true)}
|
||||||
secondary
|
secondary
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
ArrowDownTrayIcon,
|
ArrowDownTrayIcon,
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
FireIcon,
|
FireIcon,
|
||||||
|
InformationCircleIcon,
|
||||||
PencilIcon,
|
PencilIcon,
|
||||||
PlusCircleIcon,
|
PlusCircleIcon,
|
||||||
XMarkIcon,
|
XMarkIcon,
|
||||||
|
@ -28,7 +29,7 @@ import ActionTokenList from '../account/ActionTokenList'
|
||||||
import { walletBalanceForToken } from './DepositModal'
|
import { walletBalanceForToken } from './DepositModal'
|
||||||
import { floorToDecimal } from '../../utils/numbers'
|
import { floorToDecimal } from '../../utils/numbers'
|
||||||
import { handleWalletConnect } from '../wallet/ConnectWalletButton'
|
import { handleWalletConnect } from '../wallet/ConnectWalletButton'
|
||||||
import { IS_ONBOARDED_KEY } from '../../utils/constants'
|
import { IS_ONBOARDED_KEY, ONBOARDING_TOUR_KEY } from '../../utils/constants'
|
||||||
import ParticlesBackground from '../ParticlesBackground'
|
import ParticlesBackground from '../ParticlesBackground'
|
||||||
import ButtonGroup from '../forms/ButtonGroup'
|
import ButtonGroup from '../forms/ButtonGroup'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
|
@ -51,19 +52,21 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
const [submitDeposit, setSubmitDeposit] = useState(false)
|
const [submitDeposit, setSubmitDeposit] = useState(false)
|
||||||
const [sizePercentage, setSizePercentage] = useState('')
|
const [sizePercentage, setSizePercentage] = useState('')
|
||||||
const [, setIsOnboarded] = useLocalStorageState(IS_ONBOARDED_KEY)
|
const [, setIsOnboarded] = useLocalStorageState(IS_ONBOARDED_KEY)
|
||||||
|
const [, setShowTour] = useLocalStorageState(ONBOARDING_TOUR_KEY)
|
||||||
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
const walletTokens = mangoStore((s) => s.wallet.tokens)
|
||||||
|
|
||||||
const handleNextStep = () => {
|
const handleNextStep = () => {
|
||||||
setShowSetupStep(showSetupStep + 1)
|
setShowSetupStep(showSetupStep + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSaveProfile = () => {
|
// const handleSaveProfile = () => {
|
||||||
// save profile details to db then:
|
// // save profile details to db then:
|
||||||
setShowSetupStep(2)
|
// setShowSetupStep(2)
|
||||||
}
|
// }
|
||||||
|
|
||||||
const handleEndOnboarding = () => {
|
const handleShowTour = () => {
|
||||||
onClose()
|
onClose()
|
||||||
|
setShowTour(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const connectWallet = async () => {
|
const connectWallet = async () => {
|
||||||
|
@ -112,8 +115,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
})
|
})
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
setIsOnboarded(true)
|
}, [accountName, wallet, t])
|
||||||
}, [accountName, wallet, t, setIsOnboarded])
|
|
||||||
|
|
||||||
const handleDeposit = useCallback(async () => {
|
const handleDeposit = useCallback(async () => {
|
||||||
const client = mangoStore.getState().client
|
const client = mangoStore.getState().client
|
||||||
|
@ -138,7 +140,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
await actions.reloadMangoAccount()
|
await actions.reloadMangoAccount()
|
||||||
onClose()
|
setShowSetupStep(4)
|
||||||
setSubmitDeposit(false)
|
setSubmitDeposit(false)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
notify({
|
notify({
|
||||||
|
@ -150,7 +152,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
setSubmitDeposit(false)
|
setSubmitDeposit(false)
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
}, [depositAmount, depositToken, onClose, setIsOnboarded])
|
}, [depositAmount, depositToken, onClose])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mangoAccount && showSetupStep === 2) {
|
if (mangoAccount && showSetupStep === 2) {
|
||||||
|
@ -207,11 +209,11 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
>
|
>
|
||||||
<div className="min-h-screen px-4 text-center">
|
<div className="min-h-screen px-4 text-center">
|
||||||
<Dialog.Overlay
|
<Dialog.Overlay
|
||||||
className={`intro-bg pointer-events-none fixed inset-0 bg-th-bkg-1`}
|
className={`intro-bg pointer-events-none fixed inset-0 bg-th-bkg-1 opacity-80`}
|
||||||
/>
|
/>
|
||||||
<div className="absolute top-6 left-6 z-10" id="repulse">
|
{/* <div className="absolute top-6 left-6 z-10" id="repulse">
|
||||||
<img className="h-10 w-auto" src="/logos/logo-mark.svg" alt="next" />
|
<img className="h-10 w-auto" src="/logos/logo-mark.svg" alt="next" />
|
||||||
</div>
|
</div> */}
|
||||||
<div className="absolute top-6 right-6 z-10" id="repulse">
|
<div className="absolute top-6 right-6 z-10" id="repulse">
|
||||||
<IconButton hideBg onClick={() => onClose()}>
|
<IconButton hideBg onClick={() => onClose()}>
|
||||||
<XMarkIcon className="h-6 w-6 text-th-fgd-2" />
|
<XMarkIcon className="h-6 w-6 text-th-fgd-2" />
|
||||||
|
@ -220,7 +222,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
<div className="absolute bottom-0 left-0 z-10 flex h-1.5 w-full flex-grow bg-th-bkg-3">
|
<div className="absolute bottom-0 left-0 z-10 flex h-1.5 w-full flex-grow bg-th-bkg-3">
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: `${(showSetupStep / 3) * 100}%`,
|
width: `${(showSetupStep / 4) * 100}%`,
|
||||||
}}
|
}}
|
||||||
className="flex rounded bg-th-primary transition-all duration-700 ease-out"
|
className="flex rounded bg-th-primary transition-all duration-700 ease-out"
|
||||||
/>
|
/>
|
||||||
|
@ -435,7 +437,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
</Button>
|
</Button>
|
||||||
<LinkButton
|
<LinkButton
|
||||||
className="flex w-full justify-center"
|
className="flex w-full justify-center"
|
||||||
onClick={onClose}
|
onClick={() => setShowSetupStep(4)}
|
||||||
>
|
>
|
||||||
<span className="default-transition text-th-fgd-4 underline md:hover:text-th-fgd-3 md:hover:no-underline">
|
<span className="default-transition text-th-fgd-4 underline md:hover:text-th-fgd-3 md:hover:no-underline">
|
||||||
Skip for now
|
Skip for now
|
||||||
|
@ -562,7 +564,7 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
Deposit
|
Deposit
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
<LinkButton onClick={handleEndOnboarding}>
|
<LinkButton onClick={() => setShowSetupStep(4)}>
|
||||||
<span className="default-transition text-th-fgd-4 underline md:hover:text-th-fgd-3 md:hover:no-underline">
|
<span className="default-transition text-th-fgd-4 underline md:hover:text-th-fgd-3 md:hover:no-underline">
|
||||||
Skip for now
|
Skip for now
|
||||||
</span>
|
</span>
|
||||||
|
@ -571,6 +573,46 @@ const UserSetupModal = ({ isOpen, onClose }: ModalProps) => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</EnterRightExitLeft>
|
</EnterRightExitLeft>
|
||||||
|
<EnterRightExitLeft
|
||||||
|
className="absolute top-0.5 left-0 z-20 w-full rounded-lg bg-th-bkg-1 p-6"
|
||||||
|
show={showSetupStep === 4}
|
||||||
|
style={{ height: 'calc(100% - 12px)' }}
|
||||||
|
>
|
||||||
|
<div className="flex h-full flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<h2 className="mb-6 text-4xl">That's a wrap</h2>
|
||||||
|
<p className="mb-2">
|
||||||
|
We recommend taking a short tour to get familiar with our
|
||||||
|
new interface.
|
||||||
|
</p>
|
||||||
|
<p className="mb-2">
|
||||||
|
Or, jump in the deep end and start trading.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<Button
|
||||||
|
className="flex-1"
|
||||||
|
secondary
|
||||||
|
onClick={onClose}
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-center">
|
||||||
|
Get Started
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className="flex-1"
|
||||||
|
onClick={handleShowTour}
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-center">
|
||||||
|
<InformationCircleIcon className="mr-2 h-5 w-5" />
|
||||||
|
Show Tour
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</EnterRightExitLeft>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -239,15 +239,17 @@ const SwapForm = () => {
|
||||||
</EnterBottomExitBottom>
|
</EnterBottomExitBottom>
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-4 flex items-center justify-between">
|
||||||
<h3>{t('trade')}</h3>
|
<h3>{t('trade')}</h3>
|
||||||
<IconButton
|
<div id="step-eight">
|
||||||
className="text-th-fgd-3"
|
<IconButton
|
||||||
onClick={() => setShowSettings(true)}
|
className="text-th-fgd-3"
|
||||||
size="small"
|
onClick={() => setShowSettings(true)}
|
||||||
>
|
size="small"
|
||||||
<Cog8ToothIcon className="h-5 w-5" />
|
>
|
||||||
</IconButton>
|
<Cog8ToothIcon className="h-5 w-5" />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-2 flex items-center justify-between">
|
<div id="step-nine" className="mb-2 flex items-center justify-between">
|
||||||
<p className="text-th-fgd-3">{t('sell')}</p>
|
<p className="text-th-fgd-3">{t('sell')}</p>
|
||||||
<MaxSwapAmount
|
<MaxSwapAmount
|
||||||
amountWithBorrow={amountWithBorrow}
|
amountWithBorrow={amountWithBorrow}
|
||||||
|
@ -378,42 +380,43 @@ const SwapForm = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!!mangoAccount ? (
|
{/* {!!mangoAccount ? ( */}
|
||||||
<div
|
<div
|
||||||
className={`bg-th-bkg-3 px-6 transition-all ${
|
id="step-ten"
|
||||||
showHealthImpact ? 'max-h-40 py-4 ' : 'h-0'
|
className={`bg-th-bkg-3 px-6 transition-all ${
|
||||||
}`}
|
showHealthImpact ? 'max-h-40 py-4 ' : 'h-0'
|
||||||
>
|
}`}
|
||||||
<div className="flex justify-between">
|
>
|
||||||
<p className="text-sm">{t('health-impact')}</p>
|
<div className="flex justify-between">
|
||||||
<div className="flex items-center space-x-2">
|
<p className="text-sm">{t('health-impact')}</p>
|
||||||
<p className="text-sm text-th-fgd-1">{currentMaintHealth}%</p>
|
<div className="flex items-center space-x-2">
|
||||||
<ArrowRightIcon className="h-4 w-4 text-th-fgd-4" />
|
<p className="text-sm text-th-fgd-1">{currentMaintHealth}%</p>
|
||||||
<p
|
<ArrowRightIcon className="h-4 w-4 text-th-fgd-4" />
|
||||||
className={`${
|
<p
|
||||||
maintProjectedHealth! < 50 && maintProjectedHealth! > 15
|
className={`${
|
||||||
? 'text-th-orange'
|
maintProjectedHealth! < 50 && maintProjectedHealth! > 15
|
||||||
: maintProjectedHealth! <= 15
|
? 'text-th-orange'
|
||||||
? 'text-th-red'
|
: maintProjectedHealth! <= 15
|
||||||
: 'text-th-green'
|
? 'text-th-red'
|
||||||
} text-sm`}
|
: 'text-th-green'
|
||||||
|
} text-sm`}
|
||||||
|
>
|
||||||
|
{maintProjectedHealth!}%{' '}
|
||||||
|
<span
|
||||||
|
className={`text-xs ${
|
||||||
|
maintProjectedHealth! >= currentMaintHealth!
|
||||||
|
? 'text-th-green'
|
||||||
|
: 'text-th-red'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{maintProjectedHealth!}%{' '}
|
({maintProjectedHealth! >= currentMaintHealth! ? '+' : ''}
|
||||||
<span
|
{maintProjectedHealth! - currentMaintHealth!}%)
|
||||||
className={`text-xs ${
|
</span>
|
||||||
maintProjectedHealth! >= currentMaintHealth!
|
</p>
|
||||||
? 'text-th-green'
|
|
||||||
: 'text-th-red'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
({maintProjectedHealth! >= currentMaintHealth! ? '+' : ''}
|
|
||||||
{maintProjectedHealth! - currentMaintHealth!}%)
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
</div>
|
||||||
|
{/* ) : null} */}
|
||||||
</ContentBox>
|
</ContentBox>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
"react-window": "^1.8.7",
|
"react-window": "^1.8.7",
|
||||||
"recharts": "^2.1.12",
|
"recharts": "^2.1.12",
|
||||||
"tsparticles": "^2.2.4",
|
"tsparticles": "^2.2.4",
|
||||||
|
"walktour": "^5.1.1",
|
||||||
"zustand": "^4.1.1"
|
"zustand": "^4.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|
|
@ -14,6 +14,8 @@ export const ALPHA_DEPOSIT_LIMIT = 20
|
||||||
|
|
||||||
export const SIDEBAR_COLLAPSE_KEY = 'sidebar-0.1'
|
export const SIDEBAR_COLLAPSE_KEY = 'sidebar-0.1'
|
||||||
|
|
||||||
|
export const ONBOARDING_TOUR_KEY = 'showOnboardingTour'
|
||||||
|
|
||||||
export const PROFILE_CATEGORIES = [
|
export const PROFILE_CATEGORIES = [
|
||||||
'borrower',
|
'borrower',
|
||||||
'day-trader',
|
'day-trader',
|
||||||
|
|
|
@ -5445,6 +5445,11 @@ wait-on@6.0.0:
|
||||||
minimist "^1.2.5"
|
minimist "^1.2.5"
|
||||||
rxjs "^7.1.0"
|
rxjs "^7.1.0"
|
||||||
|
|
||||||
|
walktour@^5.1.1:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/walktour/-/walktour-5.1.1.tgz#951b5bce2abed0ae4209dc74d4d79f252a85e813"
|
||||||
|
integrity sha512-pRjbjjBGddgiWaWryE+H6DxOeAuUgIZJ5ck0hOVrhZ4QNgZDs1okuGMXDKx3Gi4hi/N9ESwATyyB5hb7kiK7wQ==
|
||||||
|
|
||||||
web-streams-polyfill@^3.0.3:
|
web-streams-polyfill@^3.0.3:
|
||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
|
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
|
||||||
|
|
Loading…
Reference in New Issue