account page fixes
This commit is contained in:
parent
660b63cd1c
commit
bc6dcf09ee
|
@ -52,7 +52,7 @@ const AccountActions = () => {
|
|||
return (
|
||||
<>
|
||||
{isUnownedAccount ? null : (
|
||||
<div className="grid grid-cols-4">
|
||||
<div className="grid grid-cols-4 border-t border-th-bkg-3">
|
||||
<button
|
||||
className={`${ACTION_BUTTON_CLASSES} border-r border-th-bkg-3`}
|
||||
onClick={() => handleActionModal('deposit')}
|
||||
|
|
|
@ -29,6 +29,13 @@ const AccountHeroStats = ({ accountValue }: { accountValue: number }) => {
|
|||
const router = useRouter()
|
||||
const [showPnlHistory, setShowPnlHistory] = useState(false)
|
||||
|
||||
const handleGoToStats = () => {
|
||||
const query = { ...router.query, ['view']: 'account-stats' }
|
||||
router.push({ pathname: router.pathname, query }, undefined, {
|
||||
shallow: true,
|
||||
})
|
||||
}
|
||||
|
||||
const maintHealth = useMemo(() => {
|
||||
return group && mangoAccount
|
||||
? mangoAccount.getHealthRatioUi(group, HealthType.maint)
|
||||
|
@ -244,9 +251,7 @@ const AccountHeroStats = ({ accountValue }: { accountValue: number }) => {
|
|||
</div>
|
||||
<button
|
||||
className="default-transition flex h-10 w-full items-center justify-between px-4 focus:outline-none disabled:cursor-not-allowed md:px-6 md:hover:bg-th-bkg-2"
|
||||
onClick={() =>
|
||||
router.push('/?view=account-stats', undefined, { shallow: true })
|
||||
}
|
||||
onClick={() => handleGoToStats()}
|
||||
disabled={!mangoAccountAddress}
|
||||
>
|
||||
<p>{t('account:more-account-stats')}</p>
|
||||
|
|
|
@ -92,9 +92,7 @@ const AccountOverview = () => {
|
|||
<ConnectEmptyState text={t('governance:connect-wallet')} />
|
||||
</div>
|
||||
)}
|
||||
<div className="border-t border-th-bkg-3">
|
||||
<AccountActions />
|
||||
</div>
|
||||
<AccountActions />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-12 md:col-span-4">
|
||||
|
|
|
@ -19,7 +19,9 @@ export type ViewToShow =
|
|||
|
||||
export const handleViewChange = (view: ViewToShow, router: NextRouter) => {
|
||||
const query = { ...router.query, ['view']: view }
|
||||
router.push({ pathname: router.pathname, query })
|
||||
router.push({ pathname: router.pathname, query }, undefined, {
|
||||
shallow: true,
|
||||
})
|
||||
}
|
||||
|
||||
const AccountPage = () => {
|
||||
|
|
|
@ -6,14 +6,55 @@ import { useTranslation } from 'react-i18next'
|
|||
import { formatYAxis } from 'utils/formatting'
|
||||
import FundingChart from './FundingChart'
|
||||
import VolumeChart from './VolumeChart'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { fetchFundingTotals, fetchVolumeTotals } from 'utils/account'
|
||||
import Tooltip from '@components/shared/Tooltip'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
|
||||
const AccountStats = ({ hideView }: { hideView: () => void }) => {
|
||||
const { t } = useTranslation(['common', 'account'])
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const { performanceData, loadingPerformanceData } =
|
||||
useAccountPerformanceData()
|
||||
const [pnlDaysToShow, setPnlDaysToShow] = useState('1')
|
||||
const [interestDaysToShow, setInterestDaysToShow] = useState('1')
|
||||
|
||||
const { data: fundingData, isLoading: loadingFunding } = useQuery(
|
||||
['funding', mangoAccountAddress],
|
||||
() => fetchFundingTotals(mangoAccountAddress),
|
||||
{
|
||||
cacheTime: 1000 * 60 * 10,
|
||||
staleTime: 1000 * 60,
|
||||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
enabled: !!mangoAccountAddress,
|
||||
},
|
||||
)
|
||||
|
||||
const { data: volumeTotalData, isLoading: loadingVolumeTotalData } = useQuery(
|
||||
['total-volume', mangoAccountAddress],
|
||||
() => fetchVolumeTotals(mangoAccountAddress),
|
||||
{
|
||||
cacheTime: 1000 * 60 * 10,
|
||||
staleTime: 1000 * 60,
|
||||
retry: 3,
|
||||
refetchOnWindowFocus: false,
|
||||
enabled: !!mangoAccountAddress,
|
||||
},
|
||||
)
|
||||
|
||||
const fundingTotalValue = useMemo(() => {
|
||||
if (fundingData?.length && mangoAccountAddress) {
|
||||
return fundingData.reduce(
|
||||
(a, c) => a + c.long_funding + c.short_funding,
|
||||
0,
|
||||
)
|
||||
}
|
||||
return 0.0
|
||||
}, [fundingData, mangoAccountAddress])
|
||||
|
||||
const chartData = useMemo(() => {
|
||||
if (!performanceData || !performanceData.length) return []
|
||||
const chartData = []
|
||||
|
@ -51,6 +92,7 @@ const AccountStats = ({ hideView }: { hideView: () => void }) => {
|
|||
title={t('pnl')}
|
||||
xKey="time"
|
||||
yKey="pnl"
|
||||
small
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 border-b border-th-bkg-3 px-6 py-4 md:col-span-1 md:pl-6">
|
||||
|
@ -66,13 +108,57 @@ const AccountStats = ({ hideView }: { hideView: () => void }) => {
|
|||
title={t('cumulative-interest-value')}
|
||||
xKey="time"
|
||||
yKey="interest_value"
|
||||
small
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2 h-[400px] border-b border-th-bkg-3 md:col-span-1 md:border-r">
|
||||
<FundingChart />
|
||||
<div className="col-span-2 border-b border-th-bkg-3 md:col-span-1 md:border-r">
|
||||
<div className="border-b border-th-bkg-3 px-4 pb-4 pt-3 md:px-6">
|
||||
<Tooltip
|
||||
content={t('account:tooltip-total-funding')}
|
||||
maxWidth="20rem"
|
||||
placement="top-start"
|
||||
delay={100}
|
||||
>
|
||||
<p className="tooltip-underline text-base leading-tight">
|
||||
{t('account:total-funding-earned')}
|
||||
</p>
|
||||
</Tooltip>
|
||||
{loadingFunding && mangoAccountAddress ? (
|
||||
<SheenLoader className="mt-2">
|
||||
<div className="h-7 w-16 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
) : (
|
||||
<p className="mt-0.5 text-2xl font-bold text-th-fgd-1">
|
||||
<FormatNumericValue
|
||||
value={fundingTotalValue}
|
||||
decimals={2}
|
||||
isUsd={true}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-6 py-4">
|
||||
<FundingChart />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-2 h-[400px] border-b border-th-bkg-3 md:col-span-1">
|
||||
<VolumeChart />
|
||||
<div className="col-span-2 border-b border-th-bkg-3 md:col-span-1">
|
||||
<div className="border-b border-th-bkg-3 px-4 pb-4 pt-3 md:px-6">
|
||||
<p className="tooltip-underline text-base leading-tight">
|
||||
{t('account:lifetime-volume')}
|
||||
</p>
|
||||
{loadingVolumeTotalData && mangoAccountAddress ? (
|
||||
<SheenLoader className="mt-2">
|
||||
<div className="h-7 w-16 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
) : (
|
||||
<p className="mt-0.5 text-2xl font-bold text-th-fgd-1">
|
||||
<FormatNumericValue value={volumeTotalData || 0} isUsd />
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-6 py-4">
|
||||
<VolumeChart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
import SimpleAreaChart from '@components/shared/SimpleAreaChart'
|
||||
import { COLORS } from '../../styles/colors'
|
||||
import { IconButton } from '../shared/Button'
|
||||
import { ArrowsPointingOutIcon } from '@heroicons/react/20/solid'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import SheenLoader from '../shared/SheenLoader'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { PerformanceDataItem } from 'types'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useViewport } from 'hooks/useViewport'
|
||||
import { handleViewChange } from './AccountPage'
|
||||
import useAccountPerformanceData from 'hooks/useAccountPerformanceData'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const AccountValueChart = ({
|
||||
accountValue,
|
||||
latestAccountData,
|
||||
rollingDailyData,
|
||||
}: {
|
||||
accountValue: number
|
||||
latestAccountData: PerformanceDataItem[]
|
||||
rollingDailyData: PerformanceDataItem[]
|
||||
}) => {
|
||||
const { theme } = useThemeWrapper()
|
||||
const router = useRouter()
|
||||
const { mangoAccountAddress } = useMangoAccount()
|
||||
const [showExpandChart, setShowExpandChart] = useState<boolean>(false)
|
||||
const { isTablet } = useViewport()
|
||||
const { performanceLoading: loading } = useAccountPerformanceData()
|
||||
|
||||
const accountValueChange = useMemo(() => {
|
||||
if (!accountValue || !rollingDailyData.length) return 0
|
||||
const accountValueChange = accountValue - rollingDailyData[0].account_equity
|
||||
return accountValueChange
|
||||
}, [accountValue, rollingDailyData])
|
||||
|
||||
const onHoverMenu = (open: boolean, action: string) => {
|
||||
if (
|
||||
(!open && action === 'onMouseEnter') ||
|
||||
(open && action === 'onMouseLeave')
|
||||
) {
|
||||
setShowExpandChart(!open)
|
||||
}
|
||||
}
|
||||
|
||||
const handleShowAccountValueChart = useCallback(() => {
|
||||
handleViewChange('account-value', router)
|
||||
setShowExpandChart(false)
|
||||
}, [router])
|
||||
|
||||
return !loading ? (
|
||||
rollingDailyData.length ? (
|
||||
<div
|
||||
className="relative mt-4 flex h-40 items-end md:mt-0 md:h-28 md:w-52 lg:w-56"
|
||||
onMouseEnter={() => onHoverMenu(showExpandChart, 'onMouseEnter')}
|
||||
onMouseLeave={() => onHoverMenu(showExpandChart, 'onMouseLeave')}
|
||||
>
|
||||
<SimpleAreaChart
|
||||
color={
|
||||
accountValueChange >= 0 ? COLORS.UP[theme] : COLORS.DOWN[theme]
|
||||
}
|
||||
data={rollingDailyData.concat(latestAccountData)}
|
||||
name="accountValue"
|
||||
xKey="time"
|
||||
yKey="account_equity"
|
||||
/>
|
||||
<Transition
|
||||
appear={true}
|
||||
className="absolute bottom-2 right-2"
|
||||
show={showExpandChart || isTablet}
|
||||
enter="transition ease-in duration-300"
|
||||
enterFrom="opacity-0 scale-75"
|
||||
enterTo="opacity-100 scale-100"
|
||||
leave="transition ease-out duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
hideBg
|
||||
onClick={() => handleShowAccountValueChart()}
|
||||
>
|
||||
<ArrowsPointingOutIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
</Transition>
|
||||
</div>
|
||||
) : null
|
||||
) : mangoAccountAddress ? (
|
||||
<SheenLoader className="mt-4 flex flex-1 md:mt-0">
|
||||
<div className="h-40 w-full rounded-md bg-th-bkg-2 md:h-20 md:w-52 lg:w-60" />
|
||||
</SheenLoader>
|
||||
) : null
|
||||
}
|
||||
|
||||
export default AccountValueChart
|
|
@ -31,6 +31,7 @@ import { FadeInFadeOut } from '@components/shared/Transitions'
|
|||
import ContentBox from '@components/shared/ContentBox'
|
||||
import SheenLoader from '@components/shared/SheenLoader'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
|
||||
type TempDataType = {
|
||||
[time: string]: {
|
||||
|
@ -79,7 +80,7 @@ const FundingChart = () => {
|
|||
isFetching: fetchingFunding,
|
||||
refetch,
|
||||
} = useQuery(
|
||||
['hourly-funding'],
|
||||
['hourly-funding', mangoAccountAddress],
|
||||
() => fetchHourlyFunding(mangoAccountAddress),
|
||||
{
|
||||
cacheTime: 1000 * 60 * 10,
|
||||
|
@ -167,12 +168,6 @@ const FundingChart = () => {
|
|||
const scaleDataTime = (data: HourlyFundingChartData[]) => {
|
||||
const scaledData = data.reduce((a: HourlyFundingChartData[], c) => {
|
||||
const found = a.find((item) => {
|
||||
// const threshold = daysToShow === '7' ? 14400000 : 86400000
|
||||
// const currentDataTime = new Date(c.time).getTime()
|
||||
// const date = new Date(item.time)
|
||||
// const maxTime = date.getTime() + threshold
|
||||
// return currentDataTime <= maxTime
|
||||
|
||||
const currentDataDate = new Date(c.time)
|
||||
const itemDate = new Date(item.time)
|
||||
return (
|
||||
|
@ -216,123 +211,141 @@ const FundingChart = () => {
|
|||
return filtered
|
||||
}, [chartData, daysToShow])
|
||||
|
||||
const totalForTimePeriod = useMemo(() => {
|
||||
if (!filteredData.length) return 0
|
||||
return filteredData.reduce((a, c) => a + c.total, 0)
|
||||
}, [filteredData])
|
||||
|
||||
return (
|
||||
<FadeInFadeOut show={true}>
|
||||
<ContentBox className="px-6 pt-4" hideBorder hidePadding>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-4 md:space-x-6">
|
||||
<h2 className="text-lg">{t('funding')}</h2>
|
||||
</div>
|
||||
<ChartRangeButtons
|
||||
activeValue={daysToShow}
|
||||
names={['24H', '7D', '30D']}
|
||||
values={['1', '7', '30']}
|
||||
onChange={(v) => setDaysToShow(v)}
|
||||
/>
|
||||
</div>
|
||||
<ContentBox hideBorder hidePadding>
|
||||
{loadingFunding || fetchingFunding ? (
|
||||
<SheenLoader className="mt-4 flex flex-1">
|
||||
<div className={`h-[318px] w-full rounded-lg bg-th-bkg-2`} />
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className={`h-[350px] w-full rounded-lg bg-th-bkg-2`} />
|
||||
</SheenLoader>
|
||||
) : filteredData.find((d) => Math.abs(d.total) > 0) ? (
|
||||
<div className="-mx-6 mt-6 h-80">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={filteredData}>
|
||||
<Tooltip
|
||||
cursor={{
|
||||
fill: 'var(--bkg-2)',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
content={<CustomTooltip />}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="greenGradientBar"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={1}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={0.7}
|
||||
/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="redGradientBar"
|
||||
x1="0"
|
||||
y1="1"
|
||||
x2="0"
|
||||
y2="0"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={COLORS.DOWN[theme]}
|
||||
stopOpacity={1}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={COLORS.DOWN[theme]}
|
||||
stopOpacity={0.7}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Bar dataKey="total">
|
||||
{filteredData.map((entry, index) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill={
|
||||
entry['total'] > 0
|
||||
? 'url(#greenGradientBar)'
|
||||
: 'url(#redGradientBar)'
|
||||
}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Bar>
|
||||
<XAxis
|
||||
dataKey="time"
|
||||
axisLine={false}
|
||||
dy={10}
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) => formatDateAxis(v, parseInt(daysToShow))}
|
||||
/>
|
||||
<YAxis
|
||||
dataKey="total"
|
||||
interval="preserveStartEnd"
|
||||
axisLine={false}
|
||||
dx={-10}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) => formatYAxis(v)}
|
||||
type="number"
|
||||
/>
|
||||
<ReferenceLine y={0} stroke={COLORS.BKG4[theme]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 flex h-80 flex-col items-center justify-center rounded-lg border border-th-bkg-3 p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p>{t('account:no-data')}</p>
|
||||
</div>
|
||||
<>
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<h2 className="mb-0.5 text-base font-normal text-th-fgd-3">
|
||||
{t('funding')}
|
||||
</h2>
|
||||
{totalForTimePeriod ? (
|
||||
<span className="font-display text-2xl text-th-fgd-1">
|
||||
<FormatNumericValue value={totalForTimePeriod} isUsd />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<ChartRangeButtons
|
||||
activeValue={daysToShow}
|
||||
names={['24H', '7D', '30D']}
|
||||
values={['1', '7', '30']}
|
||||
onChange={(v) => setDaysToShow(v)}
|
||||
/>
|
||||
</div>
|
||||
{filteredData.find((d) => Math.abs(d.total) > 0) ? (
|
||||
<div className="-mx-6 mt-6 h-64">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={filteredData}>
|
||||
<Tooltip
|
||||
cursor={{
|
||||
fill: 'var(--bkg-2)',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
content={<CustomTooltip />}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="greenGradientBar"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={1}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={0.7}
|
||||
/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="redGradientBar"
|
||||
x1="0"
|
||||
y1="1"
|
||||
x2="0"
|
||||
y2="0"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={COLORS.DOWN[theme]}
|
||||
stopOpacity={1}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={COLORS.DOWN[theme]}
|
||||
stopOpacity={0.7}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Bar dataKey="total">
|
||||
{filteredData.map((entry, index) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill={
|
||||
entry['total'] > 0
|
||||
? 'url(#greenGradientBar)'
|
||||
: 'url(#redGradientBar)'
|
||||
}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Bar>
|
||||
<XAxis
|
||||
dataKey="time"
|
||||
axisLine={false}
|
||||
dy={10}
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) =>
|
||||
formatDateAxis(v, parseInt(daysToShow))
|
||||
}
|
||||
/>
|
||||
<YAxis
|
||||
dataKey="total"
|
||||
interval="preserveStartEnd"
|
||||
axisLine={false}
|
||||
dx={-10}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) => formatYAxis(v)}
|
||||
type="number"
|
||||
/>
|
||||
<ReferenceLine y={0} stroke={COLORS.BKG4[theme]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 flex h-64 flex-col items-center justify-center rounded-lg border border-th-bkg-3 p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p>{t('account:no-data')}</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ContentBox>
|
||||
</FadeInFadeOut>
|
||||
|
|
|
@ -26,6 +26,7 @@ import useAccountHourlyVolumeStats from 'hooks/useAccountHourlyVolumeStats'
|
|||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { DAILY_MILLISECONDS } from 'utils/constants'
|
||||
import useThemeWrapper from 'hooks/useThemeWrapper'
|
||||
import FormatNumericValue from '@components/shared/FormatNumericValue'
|
||||
|
||||
const VolumeChart = () => {
|
||||
const { t } = useTranslation(['account', 'common', 'stats'])
|
||||
|
@ -141,101 +142,119 @@ const VolumeChart = () => {
|
|||
return filtered
|
||||
}, [chartData, daysToShow])
|
||||
|
||||
const totalForTimePeriod = useMemo(() => {
|
||||
if (!filteredData.length) return 0
|
||||
return filteredData.reduce((a, c) => a + c.total_volume_usd, 0)
|
||||
}, [filteredData])
|
||||
|
||||
return (
|
||||
<FadeInFadeOut show={true}>
|
||||
<ContentBox className="px-6 pt-4" hideBorder hidePadding>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-4 md:space-x-6">
|
||||
<h2 className="text-lg">{t('stats:volume')}</h2>
|
||||
</div>
|
||||
<ChartRangeButtons
|
||||
activeValue={daysToShow}
|
||||
names={['24H', '7D', '30D']}
|
||||
values={['1', '7', '30']}
|
||||
onChange={(v) => setDaysToShow(v)}
|
||||
/>
|
||||
</div>
|
||||
<ContentBox hideBorder hidePadding>
|
||||
{loading && mangoAccountAddress ? (
|
||||
<SheenLoader className="mt-4 flex flex-1">
|
||||
<div className={`h-[318px] w-full rounded-lg bg-th-bkg-2`} />
|
||||
<SheenLoader className="flex flex-1">
|
||||
<div className={`h-[350px] w-full rounded-lg bg-th-bkg-2`} />
|
||||
</SheenLoader>
|
||||
) : filteredData.find((d) => d.total_volume_usd > 0) ? (
|
||||
<div className="-mx-6 mt-6 h-80">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={filteredData}>
|
||||
<Tooltip
|
||||
cursor={{
|
||||
fill: 'var(--bkg-2)',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
content={<CustomTooltip />}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="greenGradientBar"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={1}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={0.7}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Bar dataKey="total_volume_usd">
|
||||
{filteredData.map((entry, index) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill="url(#greenGradientBar)"
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Bar>
|
||||
<XAxis
|
||||
dataKey="time"
|
||||
axisLine={false}
|
||||
dy={10}
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) => formatDateAxis(v, parseInt(daysToShow))}
|
||||
/>
|
||||
<YAxis
|
||||
dataKey="total_volume_usd"
|
||||
interval="preserveStartEnd"
|
||||
axisLine={false}
|
||||
dx={-10}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) => formatYAxis(v)}
|
||||
type="number"
|
||||
/>
|
||||
<ReferenceLine y={0} stroke={COLORS.BKG4[theme]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 flex h-80 flex-col items-center justify-center rounded-lg border border-th-bkg-3 p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p>{t('account:no-data')}</p>
|
||||
</div>
|
||||
<>
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<h2 className="mb-0.5 text-base font-normal text-th-fgd-3">
|
||||
{t('stats:volume')}
|
||||
</h2>
|
||||
{totalForTimePeriod ? (
|
||||
<span className="font-display text-2xl text-th-fgd-1">
|
||||
<FormatNumericValue value={totalForTimePeriod} isUsd />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<ChartRangeButtons
|
||||
activeValue={daysToShow}
|
||||
names={['24H', '7D', '30D']}
|
||||
values={['1', '7', '30']}
|
||||
onChange={(v) => setDaysToShow(v)}
|
||||
/>
|
||||
</div>
|
||||
{filteredData.find((d) => d.total_volume_usd > 0) ? (
|
||||
<div className="-mx-6 mt-6 h-64">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={filteredData}>
|
||||
<Tooltip
|
||||
cursor={{
|
||||
fill: 'var(--bkg-2)',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
content={<CustomTooltip />}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="greenGradientBar"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={1}
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stopColor={COLORS.UP[theme]}
|
||||
stopOpacity={0.7}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Bar dataKey="total_volume_usd">
|
||||
{filteredData.map((entry, index) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill="url(#greenGradientBar)"
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Bar>
|
||||
<XAxis
|
||||
dataKey="time"
|
||||
axisLine={false}
|
||||
dy={10}
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) =>
|
||||
formatDateAxis(v, parseInt(daysToShow))
|
||||
}
|
||||
/>
|
||||
<YAxis
|
||||
dataKey="total_volume_usd"
|
||||
interval="preserveStartEnd"
|
||||
axisLine={false}
|
||||
dx={-10}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={(v) => formatYAxis(v)}
|
||||
type="number"
|
||||
/>
|
||||
<ReferenceLine y={0} stroke={COLORS.BKG4[theme]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 flex h-64 flex-col items-center justify-center rounded-lg border border-th-bkg-3 p-8">
|
||||
<NoSymbolIcon className="mb-2 h-6 w-6 text-th-fgd-4" />
|
||||
<p>{t('account:no-data')}</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ContentBox>
|
||||
</FadeInFadeOut>
|
||||
|
|
|
@ -36,6 +36,8 @@ import useThemeWrapper from 'hooks/useThemeWrapper'
|
|||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const titleClasses = 'mb-0.5 text-base'
|
||||
|
||||
interface DetailedAreaOrBarChartProps {
|
||||
chartType?: 'area' | 'bar'
|
||||
customTooltip?: ContentType<number, string>
|
||||
|
@ -149,8 +151,6 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
return 0
|
||||
}
|
||||
|
||||
const titleClasses = `${small ? 'text-sm' : 'mb-0.5 text-base'} text-th-fgd-3`
|
||||
|
||||
return (
|
||||
<FadeInFadeOut show={true}>
|
||||
<ContentBox hideBorder hidePadding>
|
||||
|
@ -203,10 +203,8 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
{mouseData ? (
|
||||
<div>
|
||||
<div
|
||||
className={`flex ${
|
||||
small
|
||||
? 'h-8 items-center text-2xl'
|
||||
: 'mb-1 items-end text-4xl'
|
||||
className={`flex items-end ${
|
||||
small ? 'h-8 text-2xl' : 'mb-1 text-4xl'
|
||||
} font-display text-th-fgd-1`}
|
||||
>
|
||||
{animationSettings['number-scroll'] ? (
|
||||
|
@ -233,7 +231,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
</span>
|
||||
)}
|
||||
{!hideChange ? (
|
||||
<span className="ml-3">
|
||||
<span className={`ml-3 ${small ? 'mb-[3px]' : ''}`}>
|
||||
<Change
|
||||
change={calculateChartChange()}
|
||||
decimals={yDecimals}
|
||||
|
@ -258,10 +256,8 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
) : (
|
||||
<div>
|
||||
<div
|
||||
className={`flex ${
|
||||
small
|
||||
? 'h-8 items-center text-2xl'
|
||||
: 'mb-1 items-end text-4xl'
|
||||
className={`flex items-end ${
|
||||
small ? 'h-8 text-2xl' : 'mb-1 text-4xl'
|
||||
} font-display text-th-fgd-1`}
|
||||
>
|
||||
{animationSettings['number-scroll'] ? (
|
||||
|
@ -296,7 +292,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
</span>
|
||||
)}
|
||||
{!hideChange ? (
|
||||
<span className="ml-3">
|
||||
<span className={`ml-3 ${small ? 'mb-[3px]' : ''}`}>
|
||||
<Change
|
||||
change={calculateChartChange()}
|
||||
decimals={yDecimals}
|
||||
|
|
Loading…
Reference in New Issue