align expandable panels
This commit is contained in:
parent
835c1a11ea
commit
cbf7047bb7
|
@ -1,7 +1,5 @@
|
|||
import { FunctionComponent, useEffect, useMemo, useState } from 'react'
|
||||
import { ExternalLinkIcon, EyeOffIcon } from '@heroicons/react/outline'
|
||||
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||
import { Disclosure } from '@headlessui/react'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { AreaChart, Area, XAxis, YAxis, Tooltip } from 'recharts'
|
||||
|
@ -9,6 +7,7 @@ import useDimensions from 'react-cool-dimensions'
|
|||
import { IconButton } from './Button'
|
||||
import { LineChartIcon } from './icons'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ExpandableRow } from './TableElements'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
|
@ -326,270 +325,247 @@ const SwapTokenInfo: FunctionComponent<SwapTokenInfoProps> = ({
|
|||
{t('swap:chart-not-available')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{inputTokenInfo && outputTokenInfo && baseTokenId ? (
|
||||
<div className="w-full">
|
||||
<Disclosure>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button
|
||||
className={`border border-th-bkg-4 default-transition flex items-center justify-between mt-6 p-3 rounded-md w-full hover:bg-th-bkg-2 ${
|
||||
open
|
||||
? 'border-b-transparent rounded-b-none'
|
||||
: 'transform rotate-360'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
{inputTokenInfo.image?.small ? (
|
||||
<img
|
||||
className="rounded-full"
|
||||
src={inputTokenInfo.image?.small}
|
||||
width="32"
|
||||
height="32"
|
||||
alt={inputTokenInfo.name}
|
||||
/>
|
||||
) : null}
|
||||
<div className="ml-2.5 text-left">
|
||||
<h2 className="font-bold text-base text-th-fgd-1">
|
||||
{inputTokenInfo?.symbol?.toUpperCase()}
|
||||
</h2>
|
||||
<div className="font-normal text-th-fgd-3 text-xs">
|
||||
{inputTokenInfo.name}
|
||||
</div>
|
||||
<div className="pt-8">
|
||||
{inputTokenInfo && outputTokenInfo && baseTokenId ? (
|
||||
<ExpandableRow
|
||||
buttonTemplate={
|
||||
<div className="flex items-center justify-between text-fgd-1 w-full">
|
||||
<div className="flex items-center">
|
||||
{inputTokenInfo.image?.small ? (
|
||||
<img
|
||||
className="rounded-full"
|
||||
src={inputTokenInfo.image?.small}
|
||||
width="32"
|
||||
height="32"
|
||||
alt={inputTokenInfo.name}
|
||||
/>
|
||||
) : null}
|
||||
<div className="ml-2.5 text-left">
|
||||
<h2 className="font-bold text-base text-th-fgd-1">
|
||||
{inputTokenInfo?.symbol?.toUpperCase()}
|
||||
</h2>
|
||||
<div className="font-normal text-th-fgd-3 text-xs">
|
||||
{inputTokenInfo.name}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center space-x-3">
|
||||
{inputTokenInfo.market_data?.current_price?.usd ? (
|
||||
<div className="font-normal text-th-fgd-1">
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center space-x-3">
|
||||
{inputTokenInfo.market_data?.current_price?.usd ? (
|
||||
<div className="font-normal text-th-fgd-1">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
inputTokenInfo.market_data?.current_price.usd
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.price_change_percentage_24h ? (
|
||||
<div
|
||||
className={`font-normal text-th-fgd-1 ${
|
||||
inputTokenInfo.market_data
|
||||
.price_change_percentage_24h >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{inputTokenInfo.market_data.price_change_percentage_24h.toFixed(
|
||||
2
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
panelTemplate={
|
||||
<div>
|
||||
<div className="font-bold m-1 mt-0 pb-2 text-th-fgd-1 text-base">
|
||||
{t('market-data')}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-2 xl:grid-cols-3 grid-flow-row">
|
||||
{inputTokenInfo.market_cap_rank ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap-rank')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
#{inputTokenInfo.market_cap_rank}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.market_cap &&
|
||||
inputTokenInfo.market_data?.market_cap?.usd !== 0 ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data?.market_cap?.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.total_volume?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('daily-volume')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data?.total_volume?.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.circulating_supply ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:token-supply')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data.circulating_supply
|
||||
)}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.max_supply ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{t('swap:max-supply')}:{' '}
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data.max_supply
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.ath?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:ath')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
inputTokenInfo.market_data?.current_price.usd
|
||||
inputTokenInfo.market_data.ath.usd
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data
|
||||
?.price_change_percentage_24h ? (
|
||||
<div
|
||||
className={`font-normal text-th-fgd-1 ${
|
||||
inputTokenInfo.market_data
|
||||
.price_change_percentage_24h >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{inputTokenInfo.market_data.price_change_percentage_24h.toFixed(
|
||||
2
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<ChevronDownIcon
|
||||
className={`default-transition h-6 ml-2 w-6 text-th-fgd-3 ${
|
||||
open ? 'transform rotate-180' : 'transform rotate-360'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Panel>
|
||||
<div className="border border-th-bkg-4 border-t-0 p-3 rounded-b-md">
|
||||
<div className="font-bold m-1 mt-0 pb-2 text-th-fgd-1 text-base">
|
||||
{t('market-data')}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-2 xl:grid-cols-3 grid-flow-row">
|
||||
{inputTokenInfo.market_cap_rank ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap-rank')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
#{inputTokenInfo.market_cap_rank}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.market_cap &&
|
||||
inputTokenInfo.market_data?.market_cap?.usd !== 0 ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data?.market_cap?.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.total_volume?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('daily-volume')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data?.total_volume?.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.circulating_supply ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:token-supply')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data.circulating_supply
|
||||
)}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.max_supply ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{t('swap:max-supply')}:{' '}
|
||||
{numberCompacter.format(
|
||||
inputTokenInfo.market_data.max_supply
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.ath?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:ath')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
inputTokenInfo.market_data.ath.usd
|
||||
)}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.ath_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
inputTokenInfo.market_data
|
||||
?.ath_change_percentage?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(inputTokenInfo.market_data?.ath_change_percentage?.usd).toFixed(
|
||||
2
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.ath_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
inputTokenInfo.market_data.ath_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.atl?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:atl')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
inputTokenInfo.market_data.atl.usd
|
||||
)}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.atl_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
inputTokenInfo.market_data
|
||||
?.atl_change_percentage?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(inputTokenInfo.market_data?.atl_change_percentage?.usd).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.atl_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
inputTokenInfo.market_data.atl_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{topHolders?.inputHolders ? (
|
||||
<div className="pt-4">
|
||||
<div className="font-bold m-1 pb-3 text-th-fgd-1 text-base">
|
||||
{t('swap:top-ten')}
|
||||
</div>
|
||||
{topHolders.inputHolders.map((holder) => (
|
||||
<a
|
||||
className="border-t border-th-bkg-4 default transition flex justify-between mx-1 px-2 py-2.5 text-th-fgd-3 hover:bg-th-bkg-2"
|
||||
href={`https://explorer.solana.com/address/${holder.owner}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key={holder.owner}
|
||||
{inputTokenInfo.market_data?.ath_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
inputTokenInfo.market_data?.ath_change_percentage
|
||||
?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
<div className="text-th-fgd-3">
|
||||
{holder.owner.slice(0, 5) +
|
||||
'…' +
|
||||
holder.owner.slice(-5)}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="text-th-fgd-1">
|
||||
{numberFormatter.format(
|
||||
holder.amount / Math.pow(10, holder.decimals)
|
||||
)}
|
||||
</div>
|
||||
<ExternalLinkIcon className="h-4 ml-2 w-4" />
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
{(inputTokenInfo.market_data?.ath_change_percentage?.usd).toFixed(
|
||||
2
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.ath_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
inputTokenInfo.market_data.ath_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{inputTokenInfo.market_data?.atl?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:atl')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
inputTokenInfo.market_data.atl.usd
|
||||
)}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.atl_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
inputTokenInfo.market_data?.atl_change_percentage
|
||||
?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(inputTokenInfo.market_data?.atl_change_percentage?.usd).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{inputTokenInfo.market_data?.atl_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
inputTokenInfo.market_data.atl_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{topHolders?.inputHolders ? (
|
||||
<div className="pt-4">
|
||||
<div className="font-bold m-1 pb-3 text-th-fgd-1 text-base">
|
||||
{t('swap:top-ten')}
|
||||
</div>
|
||||
{topHolders.inputHolders.map((holder) => (
|
||||
<a
|
||||
className="border-t border-th-bkg-4 default transition flex justify-between mx-1 px-2 py-2.5 text-th-fgd-3 hover:bg-th-bkg-2"
|
||||
href={`https://explorer.solana.com/address/${holder.owner}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key={holder.owner}
|
||||
>
|
||||
<div className="text-th-fgd-3">
|
||||
{holder.owner.slice(0, 5) +
|
||||
'…' +
|
||||
holder.owner.slice(-5)}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="text-th-fgd-1">
|
||||
{numberFormatter.format(
|
||||
holder.amount / Math.pow(10, holder.decimals)
|
||||
)}
|
||||
</div>
|
||||
<ExternalLinkIcon className="h-4 ml-2 w-4" />
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
||||
{t('swap:input-info-unavailable')}
|
||||
</div>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
||||
{t('swap:input-info-unavailable')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{outputTokenInfo && quoteTokenId ? (
|
||||
<div className="w-full">
|
||||
<Disclosure>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button
|
||||
className={`border border-th-bkg-4 default-transition flex items-center justify-between mt-3 p-3 rounded-md w-full hover:bg-th-bkg-2 ${
|
||||
open
|
||||
? 'border-b-transparent rounded-b-none'
|
||||
: 'transform rotate-360'
|
||||
}`}
|
||||
>
|
||||
{outputTokenInfo && quoteTokenId ? (
|
||||
<div className="border-b border-th-bkg-4 w-full">
|
||||
<ExpandableRow
|
||||
buttonTemplate={
|
||||
<div className="flex items-center justify-between text-fgd-1 w-full">
|
||||
<div className="flex items-center">
|
||||
{outputTokenInfo.image?.small ? (
|
||||
<img
|
||||
|
@ -615,7 +591,7 @@ const SwapTokenInfo: FunctionComponent<SwapTokenInfoProps> = ({
|
|||
<div className="font-normal text-th-fgd-1">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
outputTokenInfo.market_data.current_price.usd
|
||||
outputTokenInfo.market_data?.current_price.usd
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
|
@ -636,198 +612,193 @@ const SwapTokenInfo: FunctionComponent<SwapTokenInfoProps> = ({
|
|||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<ChevronDownIcon
|
||||
className={`default-transition h-6 ml-2 w-6 text-th-fgd-3 ${
|
||||
open ? 'transform rotate-180' : 'transform rotate-360'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Panel>
|
||||
<div className="border border-th-bkg-4 border-t-0 p-3 rounded-b-md">
|
||||
<div className="font-bold m-1 mt-0 pb-2 text-th-fgd-1 text-base">
|
||||
{t('market-data')}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-2 xl:grid-cols-3 grid-flow-row">
|
||||
{outputTokenInfo.market_cap_rank ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap-rank')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
#{outputTokenInfo.market_cap_rank}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
panelTemplate={
|
||||
<div>
|
||||
<div className="font-bold m-1 mt-0 pb-2 text-th-fgd-1 text-base">
|
||||
{t('market-data')}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-2 xl:grid-cols-3 grid-flow-row">
|
||||
{outputTokenInfo.market_cap_rank ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap-rank')}
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.market_cap &&
|
||||
outputTokenInfo.market_data?.market_cap?.usd !== 0 ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap')}
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
#{outputTokenInfo.market_cap_rank}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.market_cap &&
|
||||
outputTokenInfo.market_data?.market_cap?.usd !== 0 ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:market-cap')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data?.market_cap?.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.total_volume?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('daily-volume')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data?.total_volume?.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.circulating_supply ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:token-supply')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data.circulating_supply
|
||||
)}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.max_supply ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{t('swap:max-supply')}:{' '}
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data.max_supply
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.ath?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:ath')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data?.market_cap?.usd
|
||||
{numberFormatter.format(
|
||||
outputTokenInfo.market_data.ath.usd
|
||||
)}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.ath_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
outputTokenInfo.market_data
|
||||
?.ath_change_percentage?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(outputTokenInfo.market_data?.ath_change_percentage?.usd).toFixed(
|
||||
2
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.total_volume?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('daily-volume')}
|
||||
{outputTokenInfo.market_data?.ath_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
outputTokenInfo.market_data.ath_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.atl?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:atl')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data?.total_volume?.usd
|
||||
{numberFormatter.format(
|
||||
outputTokenInfo.market_data.atl.usd
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.circulating_supply ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:token-supply')}
|
||||
</div>
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data.circulating_supply
|
||||
)}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.max_supply ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{t('swap:max-supply')}:{' '}
|
||||
{numberCompacter.format(
|
||||
outputTokenInfo.market_data.max_supply
|
||||
{outputTokenInfo.market_data?.atl_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
outputTokenInfo.market_data
|
||||
?.atl_change_percentage?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(outputTokenInfo.market_data?.atl_change_percentage?.usd).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.ath?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:ath')}
|
||||
{outputTokenInfo.market_data?.atl_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
outputTokenInfo.market_data.atl_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
outputTokenInfo.market_data.ath.usd
|
||||
)}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.ath_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
outputTokenInfo.market_data
|
||||
?.ath_change_percentage?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(outputTokenInfo.market_data?.ath_change_percentage?.usd).toFixed(
|
||||
2
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.ath_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
outputTokenInfo.market_data.ath_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{outputTokenInfo.market_data?.atl?.usd ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
<div className="text-th-fgd-3 text-xs">
|
||||
{t('swap:atl')}
|
||||
</div>
|
||||
<div className="flex">
|
||||
<div className="font-bold text-th-fgd-1 text-lg">
|
||||
$
|
||||
{numberFormatter.format(
|
||||
outputTokenInfo.market_data.atl.usd
|
||||
)}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.atl_change_percentage
|
||||
?.usd ? (
|
||||
<div
|
||||
className={`ml-1.5 mt-2 text-xs ${
|
||||
outputTokenInfo.market_data
|
||||
?.atl_change_percentage?.usd >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{(outputTokenInfo.market_data?.atl_change_percentage?.usd).toLocaleString(
|
||||
undefined,
|
||||
{
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
%
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{outputTokenInfo.market_data?.atl_date?.usd ? (
|
||||
<div className="text-th-fgd-2 text-xs">
|
||||
{dayjs(
|
||||
outputTokenInfo.market_data.atl_date.usd
|
||||
).fromNow()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{topHolders?.outputHolders ? (
|
||||
<div className="pt-4">
|
||||
<div className="font-bold m-1 pb-3 text-th-fgd-1 text-base">
|
||||
{t('swap:top-ten')}
|
||||
</div>
|
||||
{topHolders.outputHolders.map((holder) => (
|
||||
<a
|
||||
className="border-t border-th-bkg-4 default transition flex justify-between mx-1 px-2 py-2.5 text-th-fgd-3 hover:bg-th-bkg-2"
|
||||
href={`https://explorer.solana.com/address/${holder.owner}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key={holder.owner}
|
||||
>
|
||||
<div className="text-th-fgd-3">
|
||||
{holder.owner.slice(0, 5) +
|
||||
'…' +
|
||||
holder.owner.slice(-5)}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="text-th-fgd-1">
|
||||
{numberFormatter.format(
|
||||
holder.amount / Math.pow(10, holder.decimals)
|
||||
)}
|
||||
</div>
|
||||
<ExternalLinkIcon className="h-4 ml-2 w-4" />
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
||||
{t('swap:output-info-unavailable')}
|
||||
</div>
|
||||
)}
|
||||
{topHolders?.inputHolders ? (
|
||||
<div className="pt-4">
|
||||
<div className="font-bold m-1 pb-3 text-th-fgd-1 text-base">
|
||||
{t('swap:top-ten')}
|
||||
</div>
|
||||
{topHolders.inputHolders.map((holder) => (
|
||||
<a
|
||||
className="border-t border-th-bkg-4 default transition flex justify-between mx-1 px-2 py-2.5 text-th-fgd-3 hover:bg-th-bkg-2"
|
||||
href={`https://explorer.solana.com/address/${holder.owner}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key={holder.owner}
|
||||
>
|
||||
<div className="text-th-fgd-3">
|
||||
{holder.owner.slice(0, 5) +
|
||||
'…' +
|
||||
holder.owner.slice(-5)}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<div className="text-th-fgd-1">
|
||||
{numberFormatter.format(
|
||||
holder.amount / Math.pow(10, holder.decimals)
|
||||
)}
|
||||
</div>
|
||||
<ExternalLinkIcon className="h-4 ml-2 w-4" />
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
||||
{t('swap:output-info-unavailable')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import { Disclosure } from '@headlessui/react'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||
import ButtonGroup from './ButtonGroup'
|
||||
import { numberCompacter, numberFormatter } from './SwapTokenInfo'
|
||||
import Button, { IconButton } from './Button'
|
||||
import Input from './Input'
|
||||
import { SearchIcon, XIcon } from '@heroicons/react/outline'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ExpandableRow } from './TableElements'
|
||||
|
||||
const filterByVals = ['change-percent', '24h-volume']
|
||||
const timeFrameVals = ['24h', '7d', '30d']
|
||||
|
@ -155,26 +154,17 @@ const SwapTokenInsights = ({ formState, jupiterTokens, setOutputToken }) => {
|
|||
<div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
|
||||
</div>
|
||||
) : filteredTokenInsights.length > 0 ? (
|
||||
filteredTokenInsights.map((insight) => {
|
||||
const jupToken = jupiterTokens.find(
|
||||
(t) => t?.extensions?.coingeckoId === insight.id
|
||||
)
|
||||
return (
|
||||
<Disclosure key={insight.id}>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<div
|
||||
className={`border-b default-transition flex items-center p-2 hover:bg-th-bkg-2 ${
|
||||
open
|
||||
? 'bg-th-bkg-2 border-transparent'
|
||||
: 'border-th-bkg-4'
|
||||
}`}
|
||||
>
|
||||
<Disclosure.Button
|
||||
className="flex font-normal items-center justify-between text-th-fgd-1 w-full"
|
||||
key={insight.symbol}
|
||||
>
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="border-b border-th-bkg-4">
|
||||
{filteredTokenInsights.map((insight) => {
|
||||
const jupToken = jupiterTokens.find(
|
||||
(t) => t?.extensions?.coingeckoId === insight.id
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<ExpandableRow
|
||||
buttonTemplate={
|
||||
<div className="flex items-center w-full">
|
||||
<div className="flex items-center space-x-3 w-1/2">
|
||||
<div
|
||||
className={`min-w-[48px] text-xs ${
|
||||
timeframe === timeFrameVals[0] //timeframe 24h
|
||||
|
@ -233,7 +223,7 @@ const SwapTokenInsights = ({ formState, jupiterTokens, setOutputToken }) => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center pl-2 space-x-3 text-right text-xs">
|
||||
<div className="flex items-center justify-end pl-2 space-x-3 text-right text-xs w-1/2">
|
||||
<div>
|
||||
<div className="mb-[4px] text-th-fgd-4">
|
||||
{t('price')}
|
||||
|
@ -259,28 +249,21 @@ const SwapTokenInsights = ({ formState, jupiterTokens, setOutputToken }) => {
|
|||
: '?'}
|
||||
</div>
|
||||
</div>
|
||||
<ChevronDownIcon
|
||||
className={`default-transition h-5 text-th-fgd-3 w-5 ${
|
||||
open
|
||||
? 'transform rotate-180'
|
||||
: 'transform rotate-360'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
<Button
|
||||
className="hidden lg:block ml-3 pl-3 pr-3 text-xs"
|
||||
onClick={() =>
|
||||
setOutputToken({
|
||||
...formState,
|
||||
outputMint: new PublicKey(jupToken.address),
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('buy')}
|
||||
</Button>
|
||||
</div>
|
||||
<Disclosure.Panel className="bg-th-bkg-2 border-b border-th-bkg-4 px-2 pb-2">
|
||||
<Button
|
||||
className="hidden lg:block ml-3 pl-3 pr-3 text-xs"
|
||||
onClick={() =>
|
||||
setOutputToken({
|
||||
...formState,
|
||||
outputMint: new PublicKey(jupToken.address),
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('buy')}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
panelTemplate={
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 grid-flow-row">
|
||||
{insight.market_cap_rank ? (
|
||||
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
||||
|
@ -383,23 +366,12 @@ const SwapTokenInsights = ({ formState, jupiterTokens, setOutputToken }) => {
|
|||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<Button
|
||||
className="block lg:hidden my-2 text-xs w-full"
|
||||
onClick={() =>
|
||||
setOutputToken({
|
||||
...formState,
|
||||
outputMint: new PublicKey(jupToken.address),
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('buy')}
|
||||
</Button>
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
)
|
||||
})
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
||||
{t('swap:no-tokens-found')}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Disclosure } from '@headlessui/react'
|
||||
import { Disclosure, Transition } from '@headlessui/react'
|
||||
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||
import { ReactNode } from 'react'
|
||||
import { Fragment, ReactNode } from 'react'
|
||||
|
||||
export const Table = ({ children }) => (
|
||||
<table className="min-w-full">{children}</table>
|
||||
|
@ -32,14 +32,12 @@ export const Td = ({
|
|||
|
||||
type ExpandableRowProps = {
|
||||
buttonTemplate: React.ReactNode
|
||||
index: number
|
||||
panelTemplate: React.ReactNode
|
||||
rounded?: boolean
|
||||
}
|
||||
|
||||
export const ExpandableRow = ({
|
||||
buttonTemplate,
|
||||
index,
|
||||
panelTemplate,
|
||||
rounded,
|
||||
}: ExpandableRowProps) => {
|
||||
|
@ -48,9 +46,7 @@ export const ExpandableRow = ({
|
|||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button
|
||||
className={`${
|
||||
index % 2 === 0 ? `bg-th-bkg-3` : `bg-th-bkg-4`
|
||||
} default-transition flex items-center justify-between font-normal p-4 text-th-fgd-1 w-full hover:filter hover:brightness-90 focus:outline-none ${
|
||||
className={`border-t border-th-bkg-4 default-transition flex items-center justify-between font-normal p-4 text-th-fgd-1 w-full hover:bg-th-bkg-4 focus:outline-none ${
|
||||
rounded
|
||||
? open
|
||||
? 'rounded-b-none'
|
||||
|
@ -59,29 +55,29 @@ export const ExpandableRow = ({
|
|||
}`}
|
||||
>
|
||||
{buttonTemplate}
|
||||
<div className="flex items-center justify-end pl-5">
|
||||
<div className="flex items-center justify-end pl-4">
|
||||
<ChevronDownIcon
|
||||
className={`${
|
||||
open ? 'transform rotate-180' : 'transform rotate-360'
|
||||
} default-transition h-5 flex-shrink-0 w-5 text-th-primary`}
|
||||
} default-transition h-5 flex-shrink-0 w-5 text-th-fgd-1`}
|
||||
/>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Panel
|
||||
className={`${
|
||||
index % 2 === 0
|
||||
? `bg-[rgba(255,255,255,0.03)]`
|
||||
: `bg-[rgba(255,255,255,0.07)]`
|
||||
} px-4 ${
|
||||
rounded
|
||||
? open
|
||||
? 'rounded-b-md'
|
||||
: 'rounded-none'
|
||||
: 'rounded-none'
|
||||
}`}
|
||||
<Transition
|
||||
appear={true}
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition-all ease-in duration-200"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-out"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="py-4">{panelTemplate}</div>
|
||||
</Disclosure.Panel>
|
||||
<Disclosure.Panel>
|
||||
<div className="pb-4 pt-2 px-4">{panelTemplate}</div>
|
||||
</Disclosure.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
|
|
|
@ -12,8 +12,6 @@ import {
|
|||
ExclamationCircleIcon,
|
||||
InformationCircleIcon,
|
||||
} from '@heroicons/react/outline'
|
||||
import { ChevronDownIcon } from '@heroicons/react/solid'
|
||||
import { Disclosure } from '@headlessui/react'
|
||||
import Select from './Select'
|
||||
import { withdraw } from '../utils/mango'
|
||||
import {
|
||||
|
@ -24,6 +22,7 @@ import {
|
|||
} from '@blockworks-foundation/mango-client'
|
||||
import { notify } from '../utils/notifications'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ExpandableRow } from './TableElements'
|
||||
|
||||
interface WithdrawModalProps {
|
||||
onClose: () => void
|
||||
|
@ -450,85 +449,79 @@ const WithdrawModal: FunctionComponent<WithdrawModalProps> = ({
|
|||
)} ${withdrawTokenSymbol}`}</div>
|
||||
) : null}
|
||||
</div>
|
||||
<Disclosure>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button
|
||||
className={`border border-th-bkg-4 default-transition font-normal mt-4 pl-3 pr-2 py-2.5 ${
|
||||
open ? 'rounded-b-none' : 'rounded-md'
|
||||
} text-th-fgd-1 w-full hover:border-th-fgd-4 focus:outline-none`}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<span className="flex h-2 w-2 mr-2.5 relative">
|
||||
<span
|
||||
className={`animate-ping absolute inline-flex h-full w-full rounded-full ${getAccountStatusColor(
|
||||
simulation.initHealthRatio,
|
||||
false,
|
||||
true
|
||||
)} opacity-75`}
|
||||
></span>
|
||||
<span
|
||||
className={`relative inline-flex rounded-full h-2 w-2 ${getAccountStatusColor(
|
||||
simulation.initHealthRatio,
|
||||
false,
|
||||
true
|
||||
)}`}
|
||||
></span>
|
||||
</span>
|
||||
{t('health-check')}
|
||||
<Tooltip content={t('tooltip-after-withdrawal')}>
|
||||
<InformationCircleIcon
|
||||
className={`h-5 w-5 ml-2 text-th-primary cursor-help`}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<ChevronDownIcon
|
||||
className={`default-transition h-5 w-5 mr-1 ${
|
||||
open ? 'transform rotate-180' : 'transform rotate-360'
|
||||
}`}
|
||||
/>
|
||||
<div className="border-b border-th-bkg-4 pt-4">
|
||||
<ExpandableRow
|
||||
buttonTemplate={
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<span className="flex h-2 w-2 mr-2.5 relative">
|
||||
<span
|
||||
className={`animate-ping absolute inline-flex h-full w-full rounded-full ${getAccountStatusColor(
|
||||
simulation.initHealthRatio,
|
||||
false,
|
||||
true
|
||||
)} opacity-75`}
|
||||
></span>
|
||||
<span
|
||||
className={`relative inline-flex rounded-full h-2 w-2 ${getAccountStatusColor(
|
||||
simulation.initHealthRatio,
|
||||
false,
|
||||
true
|
||||
)}`}
|
||||
></span>
|
||||
</span>
|
||||
{t('health-check')}
|
||||
<Tooltip content={t('tooltip-after-withdrawal')}>
|
||||
<InformationCircleIcon
|
||||
className={`h-5 w-5 ml-2 text-th-primary cursor-help`}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Panel
|
||||
className={`border border-th-bkg-4 border-t-0 p-4 rounded-b-md`}
|
||||
>
|
||||
{simulation ? (
|
||||
<div>
|
||||
<div className="flex justify-between pb-2">
|
||||
<p className="mb-0">{t('account-value')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
${simulation.equity.toFixed(2)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between pb-2">
|
||||
<p className="mb-0">{t('account-risk')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
{getAccountStatusColor(
|
||||
simulation.initHealthRatio,
|
||||
true
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between pb-2">
|
||||
<p className="mb-0">{t('leverage')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
{simulation.leverage.toFixed(2)}x
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between">
|
||||
<p className="mb-0">{t('borrow-value')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
${simulation.liabsVal.toFixed(2)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
panelTemplate={
|
||||
simulation ? (
|
||||
<div>
|
||||
<div className="flex justify-between pb-2">
|
||||
<p className="mb-0">{t('account-value')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
$
|
||||
{simulation.equity.toLocaleString(undefined, {
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</Disclosure.Panel>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
<div className="flex justify-between pb-2">
|
||||
<p className="mb-0">{t('account-risk')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
{getAccountStatusColor(
|
||||
simulation.initHealthRatio,
|
||||
true
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between pb-2">
|
||||
<p className="mb-0">{t('leverage')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
{simulation.leverage.toFixed(2)}x
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between">
|
||||
<p className="mb-0">{t('borrow-value')}</p>
|
||||
<div className="text-th-fgd-1">
|
||||
$
|
||||
{simulation.liabsVal.toLocaleString(undefined, {
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={`mt-6 flex flex-col items-center`}>
|
||||
<Button
|
||||
onClick={handleWithdraw}
|
||||
|
|
|
@ -212,7 +212,6 @@ export default function AccountBorrows() {
|
|||
</div>
|
||||
}
|
||||
key={`${asset.symbol}${i}`}
|
||||
index={i}
|
||||
panelTemplate={
|
||||
<>
|
||||
<div className="grid grid-cols-2 grid-flow-row gap-4 pb-4">
|
||||
|
@ -454,7 +453,6 @@ export default function AccountBorrows() {
|
|||
</div>
|
||||
}
|
||||
key={`${token.symbol}${i}`}
|
||||
index={i}
|
||||
panelTemplate={
|
||||
<div className="grid grid-cols-2 grid-flow-row gap-4">
|
||||
<div className="text-left">
|
||||
|
@ -467,27 +465,29 @@ export default function AccountBorrows() {
|
|||
.toNumber()
|
||||
)}
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="pb-0.5 text-th-fgd-3 text-xs">
|
||||
{t('max-borrow')}
|
||||
{mangoAccount ? (
|
||||
<div className="text-left">
|
||||
<div className="pb-0.5 text-th-fgd-3 text-xs">
|
||||
{t('max-borrow')}
|
||||
</div>
|
||||
{mangoAccount
|
||||
? mangoAccount
|
||||
.getMaxWithBorrowForToken(
|
||||
mangoGroup,
|
||||
mangoCache,
|
||||
tokenIndex
|
||||
)
|
||||
.mul(I80F48.fromString('0.995'))
|
||||
.toNumber()
|
||||
.toLocaleString(undefined, {
|
||||
minimumFractionDigits:
|
||||
tokenPrecision[token.symbol],
|
||||
maximumFractionDigits:
|
||||
tokenPrecision[token.symbol],
|
||||
})
|
||||
: null}
|
||||
</div>
|
||||
{mangoAccount
|
||||
? mangoAccount
|
||||
.getMaxWithBorrowForToken(
|
||||
mangoGroup,
|
||||
mangoCache,
|
||||
tokenIndex
|
||||
)
|
||||
.mul(I80F48.fromString('0.995'))
|
||||
.toNumber()
|
||||
.toLocaleString(undefined, {
|
||||
minimumFractionDigits:
|
||||
tokenPrecision[token.symbol],
|
||||
maximumFractionDigits:
|
||||
tokenPrecision[token.symbol],
|
||||
})
|
||||
: null}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="text-left">
|
||||
<div className="pb-0.5 text-th-fgd-3 text-xs">
|
||||
{t('liquidity')}
|
||||
|
@ -505,7 +505,7 @@ export default function AccountBorrows() {
|
|||
</div>
|
||||
<Button
|
||||
onClick={() => handleShowBorrow(token.symbol)}
|
||||
className="text-xs pt-0 pb-0 h-8 w-full"
|
||||
className="col-span-2 text-xs pt-0 pb-0 h-8"
|
||||
disabled={
|
||||
!connected || loadingMangoAccount || !canWithdraw
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ const MobileTableHeader = ({
|
|||
colThreeHeader = null,
|
||||
}: MobileTableHeaderProps) => {
|
||||
return (
|
||||
<div className="flex justify-between pb-2 pl-4 pr-14 text-th-fgd-3 text-xs">
|
||||
<div className="flex justify-between pb-2 pl-4 pr-12 text-th-fgd-3 text-xs">
|
||||
<div>{colOneHeader}</div>
|
||||
<div>{colTwoHeader}</div>
|
||||
{colThreeHeader ? <div>{colThreeHeader}</div> : null}
|
||||
|
|
Loading…
Reference in New Issue