better chart empty states
This commit is contained in:
parent
8e27126d63
commit
ca94ea07d0
|
@ -19,6 +19,27 @@ import Button from '@components/shared/Button'
|
|||
const EMPTY_STATE_WRAPPER_CLASSES =
|
||||
'flex h-[180px] flex-col justify-center pb-4 md:h-full'
|
||||
|
||||
const DEFAULT_CHART_DATA = [
|
||||
{
|
||||
account_equity: 0,
|
||||
time: dayjs().subtract(1, 'hour').toISOString(),
|
||||
borrow_interest_cumulative_usd: 0,
|
||||
deposit_interest_cumulative_usd: 0,
|
||||
pnl: 0,
|
||||
spot_value: 0,
|
||||
transfer_balance: 0,
|
||||
},
|
||||
{
|
||||
account_equity: 0,
|
||||
time: dayjs().toISOString(),
|
||||
borrow_interest_cumulative_usd: 0,
|
||||
deposit_interest_cumulative_usd: 0,
|
||||
pnl: 0,
|
||||
spot_value: 0,
|
||||
transfer_balance: 0,
|
||||
},
|
||||
]
|
||||
|
||||
const AccountOverview = () => {
|
||||
const { t } = useTranslation(['common', 'governance'])
|
||||
const { group } = useMangoGroup()
|
||||
|
@ -35,12 +56,12 @@ const AccountOverview = () => {
|
|||
}, [group, mangoAccount])
|
||||
|
||||
const latestAccountData = useMemo(() => {
|
||||
if (!accountValue || !performanceData || !performanceData.length) return []
|
||||
if (!performanceData || !performanceData?.length) return []
|
||||
const latestDataItem = performanceData[performanceData.length - 1]
|
||||
return [
|
||||
{
|
||||
account_equity: accountValue,
|
||||
time: dayjs(Date.now()).toISOString(),
|
||||
time: dayjs().toISOString(),
|
||||
borrow_interest_cumulative_usd:
|
||||
latestDataItem.borrow_interest_cumulative_usd,
|
||||
deposit_interest_cumulative_usd:
|
||||
|
@ -52,8 +73,13 @@ const AccountOverview = () => {
|
|||
]
|
||||
}, [accountValue, performanceData])
|
||||
|
||||
const chartData =
|
||||
performanceData && performanceData?.length ? performanceData : []
|
||||
const chartData = useMemo(() => {
|
||||
if (performanceData && performanceData?.length)
|
||||
return performanceData.concat(latestAccountData)
|
||||
if (!latestAccountData.length) {
|
||||
return DEFAULT_CHART_DATA
|
||||
}
|
||||
}, [latestAccountData, performanceData])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -64,7 +90,7 @@ const AccountOverview = () => {
|
|||
<div className="px-4 pb-4 md:px-6">
|
||||
<DetailedAreaOrBarChart
|
||||
changeAsPercent
|
||||
data={chartData.concat(latestAccountData)}
|
||||
data={chartData}
|
||||
daysToShow={daysToShow}
|
||||
setDaysToShow={setDaysToShow}
|
||||
loading={loadingPerformanceData || initialLoad}
|
||||
|
|
|
@ -129,7 +129,7 @@ const AccountStats = ({ hideView }: { hideView: () => void }) => {
|
|||
</Tooltip>
|
||||
{loadingFunding && mangoAccountAddress ? (
|
||||
<SheenLoader className="mt-2">
|
||||
<div className="h-7 w-16 bg-th-bkg-2" />
|
||||
<div className="h-[26px] w-16 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
) : (
|
||||
<p className="mt-0.5 text-2xl font-bold text-th-fgd-1">
|
||||
|
@ -142,7 +142,7 @@ const AccountStats = ({ hideView }: { hideView: () => void }) => {
|
|||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="px-6 py-4">
|
||||
<div className="px-6 py-4 lg:py-6">
|
||||
<FundingChart />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -153,7 +153,7 @@ const AccountStats = ({ hideView }: { hideView: () => void }) => {
|
|||
</p>
|
||||
{loadingVolumeTotalData && mangoAccountAddress ? (
|
||||
<SheenLoader className="mt-2">
|
||||
<div className="h-7 w-16 bg-th-bkg-2" />
|
||||
<div className="h-[26px] w-16 bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
) : (
|
||||
<p className="mt-0.5 text-2xl font-bold text-th-fgd-1">
|
||||
|
|
|
@ -19,12 +19,7 @@ import FlipNumbers from 'react-flip-numbers'
|
|||
import ContentBox from './ContentBox'
|
||||
import SheenLoader from './SheenLoader'
|
||||
import { COLORS } from '../../styles/colors'
|
||||
import { IconButton } from './Button'
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
ArrowsRightLeftIcon,
|
||||
NoSymbolIcon,
|
||||
} from '@heroicons/react/20/solid'
|
||||
import { ArrowsRightLeftIcon, NoSymbolIcon } from '@heroicons/react/20/solid'
|
||||
import { FadeInFadeOut } from './Transitions'
|
||||
import ChartRangeButtons from './ChartRangeButtons'
|
||||
import Change from './Change'
|
||||
|
@ -57,7 +52,6 @@ interface DetailedAreaOrBarChartProps {
|
|||
domain?: AxisDomain
|
||||
heightClass?: string
|
||||
hideChange?: boolean
|
||||
hideChart?: () => void
|
||||
hideAxis?: boolean
|
||||
isPrivate?: boolean
|
||||
loaderHeightClass?: string
|
||||
|
@ -98,7 +92,6 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
domain,
|
||||
heightClass,
|
||||
hideChange,
|
||||
hideChart,
|
||||
hideAxis,
|
||||
isPrivate,
|
||||
loaderHeightClass,
|
||||
|
@ -203,7 +196,7 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
} w-full rounded-lg bg-th-bkg-2`}
|
||||
/>
|
||||
</SheenLoader>
|
||||
) : filteredData.length ? (
|
||||
) : (
|
||||
<div className="relative">
|
||||
{setDaysToShow ? (
|
||||
<div className="mb-4 sm:absolute sm:-top-1 sm:right-0 sm:mb-0 sm:flex sm:justify-end">
|
||||
|
@ -215,443 +208,448 @@ const DetailedAreaOrBarChart: FunctionComponent<
|
|||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex flex-col md:flex-row md:items-start md:space-x-6">
|
||||
{hideChart ? (
|
||||
<IconButton
|
||||
className="mb-6"
|
||||
onClick={hideChart}
|
||||
size="medium"
|
||||
{title ? (
|
||||
tooltipContent ? (
|
||||
<Tooltip content={tooltipContent}>
|
||||
<p
|
||||
className={`${titleClasses}
|
||||
tooltip-underline`}
|
||||
>
|
||||
<ArrowLeftIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
) : null}
|
||||
<div>
|
||||
{title ? (
|
||||
tooltipContent ? (
|
||||
<Tooltip content={tooltipContent}>
|
||||
<p
|
||||
className={`${titleClasses}
|
||||
tooltip-underline`}
|
||||
>
|
||||
{title}
|
||||
</p>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<p className={titleClasses}>{title}</p>
|
||||
)
|
||||
) : null}
|
||||
{mouseData ? (
|
||||
{title}
|
||||
</p>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<p className={titleClasses}>{title}</p>
|
||||
)
|
||||
) : null}
|
||||
{filteredData.length ? (
|
||||
<>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex flex-col md:flex-row md:items-start md:space-x-6">
|
||||
<div>
|
||||
<div
|
||||
className={`flex items-end ${
|
||||
small ? 'h-8 text-2xl' : 'mb-1 text-4xl'
|
||||
} font-display text-th-fgd-1`}
|
||||
>
|
||||
{animationSettings['number-scroll'] ? (
|
||||
isPrivate && privacyMode ? (
|
||||
<span>{PRIVATE_MODE_STRING}</span>
|
||||
) : (
|
||||
<FlipNumbers
|
||||
height={small ? 24 : 40}
|
||||
width={small ? 17 : 30}
|
||||
play
|
||||
numbers={`${
|
||||
mouseData[yKey] < 0 ? '-' : ''
|
||||
}${prefix}${formatNumericValue(
|
||||
Math.abs(mouseData[yKey]),
|
||||
yDecimals,
|
||||
)}${suffix}`}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<span className="tabular-nums">
|
||||
{mouseData[yKey] < 0 ? '-' : ''}
|
||||
{prefix}
|
||||
<FormatNumericValue
|
||||
value={Math.abs(mouseData[yKey])}
|
||||
decimals={yDecimals}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
{suffix}
|
||||
</span>
|
||||
)}
|
||||
{!hideChange ? (
|
||||
{mouseData ? (
|
||||
<div>
|
||||
<div
|
||||
className={`ml-3 flex items-center ${
|
||||
small ? 'mb-[3px]' : 'mb-0.5'
|
||||
}`}
|
||||
className={`flex items-end ${
|
||||
small ? 'h-8 text-2xl' : 'mb-1 text-4xl'
|
||||
} font-display text-th-fgd-1`}
|
||||
>
|
||||
<Change
|
||||
change={calculateChartChange()}
|
||||
decimals={!showChangePercentage ? yDecimals : 2}
|
||||
prefix={!showChangePercentage ? prefix : ''}
|
||||
suffix={!showChangePercentage ? suffix : '%'}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
{changeAsPercent ? (
|
||||
<ToggleChangeTypeButton
|
||||
changeType={showChangePercentage}
|
||||
setChangeType={setShowChangePercentage}
|
||||
/>
|
||||
{animationSettings['number-scroll'] ? (
|
||||
isPrivate && privacyMode ? (
|
||||
<span>{PRIVATE_MODE_STRING}</span>
|
||||
) : (
|
||||
<FlipNumbers
|
||||
height={small ? 24 : 40}
|
||||
width={small ? 17 : 30}
|
||||
play
|
||||
numbers={`${
|
||||
mouseData[yKey] < 0 ? '-' : ''
|
||||
}${prefix}${formatNumericValue(
|
||||
Math.abs(mouseData[yKey]),
|
||||
yDecimals,
|
||||
)}${suffix}`}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<span className="tabular-nums">
|
||||
{mouseData[yKey] < 0 ? '-' : ''}
|
||||
{prefix}
|
||||
<FormatNumericValue
|
||||
value={Math.abs(mouseData[yKey])}
|
||||
decimals={yDecimals}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
{suffix}
|
||||
</span>
|
||||
)}
|
||||
{!hideChange ? (
|
||||
<div
|
||||
className={`ml-3 flex items-center ${
|
||||
small ? 'mb-[3px]' : 'mb-0.5'
|
||||
}`}
|
||||
>
|
||||
<Change
|
||||
change={calculateChartChange()}
|
||||
decimals={
|
||||
!showChangePercentage ? yDecimals : 2
|
||||
}
|
||||
prefix={!showChangePercentage ? prefix : ''}
|
||||
suffix={!showChangePercentage ? suffix : '%'}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
{changeAsPercent ? (
|
||||
<ToggleChangeTypeButton
|
||||
changeType={showChangePercentage}
|
||||
setChangeType={setShowChangePercentage}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<p
|
||||
className={`${
|
||||
small ? 'text-xs' : 'text-sm'
|
||||
} text-th-fgd-4`}
|
||||
>
|
||||
{formatXKeyHeading
|
||||
? formatXKeyHeading(mouseData[xKey])
|
||||
: dayjs(mouseData[xKey]).format(
|
||||
tooltipDateFormat
|
||||
? tooltipDateFormat
|
||||
: 'DD MMM YY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div
|
||||
className={`flex items-end ${
|
||||
small ? 'h-8 text-2xl' : 'mb-1 text-4xl'
|
||||
} font-display text-th-fgd-1`}
|
||||
>
|
||||
{animationSettings['number-scroll'] ? (
|
||||
isPrivate && privacyMode ? (
|
||||
<span>{PRIVATE_MODE_STRING}</span>
|
||||
) : (
|
||||
<FlipNumbers
|
||||
height={small ? 24 : 40}
|
||||
width={small ? 17 : 30}
|
||||
play
|
||||
numbers={`${
|
||||
filteredData[filteredData.length - 1][yKey] < 0
|
||||
<p
|
||||
className={`${
|
||||
small ? 'text-xs' : 'text-sm'
|
||||
} text-th-fgd-4`}
|
||||
>
|
||||
{formatXKeyHeading
|
||||
? formatXKeyHeading(mouseData[xKey])
|
||||
: dayjs(mouseData[xKey]).format(
|
||||
tooltipDateFormat
|
||||
? tooltipDateFormat
|
||||
: 'DD MMM YY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div
|
||||
className={`flex items-end ${
|
||||
small ? 'h-8 text-2xl' : 'mb-1 text-4xl'
|
||||
} font-display text-th-fgd-1`}
|
||||
>
|
||||
{animationSettings['number-scroll'] ? (
|
||||
isPrivate && privacyMode ? (
|
||||
<span>{PRIVATE_MODE_STRING}</span>
|
||||
) : (
|
||||
<FlipNumbers
|
||||
height={small ? 24 : 40}
|
||||
width={small ? 17 : 30}
|
||||
play
|
||||
numbers={`${
|
||||
filteredData[filteredData.length - 1][
|
||||
yKey
|
||||
] < 0
|
||||
? '-'
|
||||
: ''
|
||||
}${prefix}${formatNumericValue(
|
||||
Math.abs(
|
||||
filteredData[filteredData.length - 1][
|
||||
yKey
|
||||
],
|
||||
),
|
||||
yDecimals,
|
||||
)}${suffix}`}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<span>
|
||||
{filteredData[filteredData.length - 1][yKey] < 0
|
||||
? '-'
|
||||
: ''
|
||||
}${prefix}${formatNumericValue(
|
||||
Math.abs(
|
||||
filteredData[filteredData.length - 1][yKey],
|
||||
),
|
||||
yDecimals,
|
||||
)}${suffix}`}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<span>
|
||||
{filteredData[filteredData.length - 1][yKey] < 0
|
||||
? '-'
|
||||
: ''}
|
||||
{prefix}
|
||||
<span className="tabular-nums">
|
||||
<FormatNumericValue
|
||||
value={
|
||||
data
|
||||
? Math.abs(data[data.length - 1][yKey])
|
||||
: 0
|
||||
}
|
||||
decimals={yDecimals}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
</span>
|
||||
{suffix}
|
||||
</span>
|
||||
)}
|
||||
{!hideChange ? (
|
||||
<div
|
||||
className={`ml-3 flex items-center ${
|
||||
small ? 'mb-[3px]' : 'mb-0.5'
|
||||
}`}
|
||||
>
|
||||
<Change
|
||||
change={calculateChartChange()}
|
||||
decimals={!showChangePercentage ? yDecimals : 2}
|
||||
prefix={!showChangePercentage ? prefix : ''}
|
||||
suffix={!showChangePercentage ? suffix : '%'}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
{changeAsPercent ? (
|
||||
<ToggleChangeTypeButton
|
||||
changeType={showChangePercentage}
|
||||
setChangeType={setShowChangePercentage}
|
||||
/>
|
||||
: ''}
|
||||
{prefix}
|
||||
<span className="tabular-nums">
|
||||
<FormatNumericValue
|
||||
value={
|
||||
data
|
||||
? Math.abs(data[data.length - 1][yKey])
|
||||
: 0
|
||||
}
|
||||
decimals={yDecimals}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
</span>
|
||||
{suffix}
|
||||
</span>
|
||||
)}
|
||||
{!hideChange ? (
|
||||
<div
|
||||
className={`ml-3 flex items-center ${
|
||||
small ? 'mb-[3px]' : 'mb-0.5'
|
||||
}`}
|
||||
>
|
||||
<Change
|
||||
change={calculateChartChange()}
|
||||
decimals={
|
||||
!showChangePercentage ? yDecimals : 2
|
||||
}
|
||||
prefix={!showChangePercentage ? prefix : ''}
|
||||
suffix={!showChangePercentage ? suffix : '%'}
|
||||
isPrivate={isPrivate}
|
||||
/>
|
||||
{changeAsPercent ? (
|
||||
<ToggleChangeTypeButton
|
||||
changeType={showChangePercentage}
|
||||
setChangeType={setShowChangePercentage}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<p
|
||||
className={`${
|
||||
small ? 'text-xs' : 'text-sm'
|
||||
} text-th-fgd-4`}
|
||||
>
|
||||
{formatXKeyHeading
|
||||
? formatXKeyHeading(
|
||||
filteredData[filteredData.length - 1][xKey],
|
||||
)
|
||||
: dayjs(
|
||||
filteredData[filteredData.length - 1][xKey],
|
||||
).format(
|
||||
tooltipDateFormat
|
||||
? tooltipDateFormat
|
||||
: 'DD MMM YY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
<p
|
||||
className={`${
|
||||
small ? 'text-xs' : 'text-sm'
|
||||
} text-th-fgd-4`}
|
||||
>
|
||||
{formatXKeyHeading
|
||||
? formatXKeyHeading(
|
||||
filteredData[filteredData.length - 1][xKey],
|
||||
)
|
||||
: dayjs(
|
||||
filteredData[filteredData.length - 1][xKey],
|
||||
).format(
|
||||
tooltipDateFormat
|
||||
? tooltipDateFormat
|
||||
: 'DD MMM YY, h:mma',
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`-mt-1 ${
|
||||
heightClass ? heightClass : 'h-96'
|
||||
} w-auto`}
|
||||
>
|
||||
<div className="-mx-6 mt-6 h-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
{chartType === 'area' ? (
|
||||
<AreaChart
|
||||
data={filteredData}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<RechartsTooltip
|
||||
cursor={{
|
||||
strokeOpacity: 0.09,
|
||||
}}
|
||||
content={customTooltip ? customTooltip : <></>}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={`gradientArea-${title?.replace(
|
||||
/[^a-zA-Z]/g,
|
||||
'',
|
||||
)}`}
|
||||
x1="0"
|
||||
y1={flipGradientCoords ? '1' : '0'}
|
||||
x2="0"
|
||||
y2={flipGradientCoords ? '0' : '1'}
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.UP[theme]
|
||||
: COLORS.DOWN[theme]
|
||||
}
|
||||
stopOpacity={0.15}
|
||||
/>
|
||||
<stop
|
||||
offset="99%"
|
||||
stopColor={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.UP[theme]
|
||||
: COLORS.DOWN[theme]
|
||||
}
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Area
|
||||
isAnimationActive={false}
|
||||
type="monotone"
|
||||
dataKey={yKey}
|
||||
stroke={
|
||||
isNaN(calculateChartChange())
|
||||
? COLORS.FGD4[theme]
|
||||
: calculateChartChange() >= 0
|
||||
? COLORS.UP[theme]
|
||||
: COLORS.DOWN[theme]
|
||||
}
|
||||
strokeWidth={1.5}
|
||||
fill={`url(#gradientArea-${title?.replace(
|
||||
/[^a-zA-Z]/g,
|
||||
'',
|
||||
)})`}
|
||||
/>
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
dataKey={xKey}
|
||||
hide={hideAxis}
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={
|
||||
xAxisType !== 'number'
|
||||
? (d) => formatDateAxis(d, parseInt(daysToShow))
|
||||
: undefined
|
||||
}
|
||||
type={xAxisType}
|
||||
>
|
||||
{xAxisLabel ? (
|
||||
<Label
|
||||
value={xAxisLabel}
|
||||
offset={-2}
|
||||
position="insideBottom"
|
||||
fontSize={10}
|
||||
fill="var(--fgd-3)"
|
||||
/>
|
||||
) : null}
|
||||
</XAxis>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
dataKey={yKey}
|
||||
hide={hideAxis}
|
||||
minTickGap={20}
|
||||
type="number"
|
||||
domain={
|
||||
domain
|
||||
? domain
|
||||
: ([dataMin, dataMax]) => {
|
||||
const difference = dataMax - dataMin
|
||||
|
||||
if (difference < 0.01) {
|
||||
return [dataMin - 0.001, dataMax + 0.001]
|
||||
} else if (difference < 0.1) {
|
||||
return [dataMin - 0.01, dataMax + 0.01]
|
||||
} else if (difference < 1) {
|
||||
return [dataMin - 0.1, dataMax + 0.11]
|
||||
} else if (difference < 10) {
|
||||
return [dataMin - 1, dataMax + 1]
|
||||
} else {
|
||||
return [dataMin, dataMax]
|
||||
}
|
||||
}
|
||||
}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickFormatter={
|
||||
tickFormat ? (v) => tickFormat(v) : undefined
|
||||
}
|
||||
tickLine={false}
|
||||
/>
|
||||
{showZeroLine ? (
|
||||
<ReferenceLine
|
||||
y={0}
|
||||
stroke="var(--fgd-4)"
|
||||
strokeDasharray="2 2"
|
||||
/>
|
||||
) : null}
|
||||
</AreaChart>
|
||||
) : (
|
||||
<BarChart
|
||||
data={filteredData}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<RechartsTooltip
|
||||
cursor={{
|
||||
fill: 'var(--bkg-2)',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
content={customTooltip ? 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={yKey}>
|
||||
{filteredData.map((entry, index) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill={
|
||||
entry[yKey] > 0
|
||||
? 'url(#greenGradientBar)'
|
||||
: 'url(#redGradientBar)'
|
||||
}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Bar>
|
||||
<XAxis
|
||||
dataKey={xKey}
|
||||
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={yKey}
|
||||
interval="preserveStartEnd"
|
||||
axisLine={false}
|
||||
dx={-10}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={
|
||||
tickFormat ? (v) => tickFormat(v) : undefined
|
||||
}
|
||||
type="number"
|
||||
/>
|
||||
<ReferenceLine y={0} stroke={COLORS.BKG4[theme]} />
|
||||
</BarChart>
|
||||
)}
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div
|
||||
className={`flex ${
|
||||
heightClass ? heightClass : 'h-96'
|
||||
} mt-4 items-center justify-center rounded-lg border border-th-bkg-3 p-8 text-th-fgd-3`}
|
||||
>
|
||||
<div>
|
||||
<NoSymbolIcon className="mx-auto mb-1 h-6 w-6 text-th-fgd-4" />
|
||||
<p className="text-th-fgd-3">{t('no-data')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`-mt-1 ${heightClass ? heightClass : 'h-96'} w-auto`}
|
||||
>
|
||||
<div className="-mx-6 mt-6 h-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
{chartType === 'area' ? (
|
||||
<AreaChart
|
||||
data={filteredData}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<RechartsTooltip
|
||||
cursor={{
|
||||
strokeOpacity: 0.09,
|
||||
}}
|
||||
content={customTooltip ? customTooltip : <></>}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={`gradientArea-${title?.replace(
|
||||
/[^a-zA-Z]/g,
|
||||
'',
|
||||
)}`}
|
||||
x1="0"
|
||||
y1={flipGradientCoords ? '1' : '0'}
|
||||
x2="0"
|
||||
y2={flipGradientCoords ? '0' : '1'}
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.UP[theme]
|
||||
: COLORS.DOWN[theme]
|
||||
}
|
||||
stopOpacity={0.15}
|
||||
/>
|
||||
<stop
|
||||
offset="99%"
|
||||
stopColor={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.UP[theme]
|
||||
: COLORS.DOWN[theme]
|
||||
}
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Area
|
||||
isAnimationActive={false}
|
||||
type="monotone"
|
||||
dataKey={yKey}
|
||||
stroke={
|
||||
isNaN(calculateChartChange())
|
||||
? COLORS.FGD4[theme]
|
||||
: calculateChartChange() >= 0
|
||||
? COLORS.UP[theme]
|
||||
: COLORS.DOWN[theme]
|
||||
}
|
||||
strokeWidth={1.5}
|
||||
fill={`url(#gradientArea-${title?.replace(
|
||||
/[^a-zA-Z]/g,
|
||||
'',
|
||||
)})`}
|
||||
/>
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
dataKey={xKey}
|
||||
hide={hideAxis}
|
||||
minTickGap={20}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={
|
||||
xAxisType !== 'number'
|
||||
? (d) => formatDateAxis(d, parseInt(daysToShow))
|
||||
: undefined
|
||||
}
|
||||
type={xAxisType}
|
||||
>
|
||||
{xAxisLabel ? (
|
||||
<Label
|
||||
value={xAxisLabel}
|
||||
offset={-2}
|
||||
position="insideBottom"
|
||||
fontSize={10}
|
||||
fill="var(--fgd-3)"
|
||||
/>
|
||||
) : null}
|
||||
</XAxis>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
dataKey={yKey}
|
||||
hide={hideAxis}
|
||||
minTickGap={20}
|
||||
type="number"
|
||||
domain={
|
||||
domain
|
||||
? domain
|
||||
: ([dataMin, dataMax]) => {
|
||||
const difference = dataMax - dataMin
|
||||
|
||||
if (difference < 0.01) {
|
||||
return [dataMin - 0.001, dataMax + 0.001]
|
||||
} else if (difference < 0.1) {
|
||||
return [dataMin - 0.01, dataMax + 0.01]
|
||||
} else if (difference < 1) {
|
||||
return [dataMin - 0.1, dataMax + 0.11]
|
||||
} else if (difference < 10) {
|
||||
return [dataMin - 1, dataMax + 1]
|
||||
} else {
|
||||
return [dataMin, dataMax]
|
||||
}
|
||||
}
|
||||
}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickFormatter={
|
||||
tickFormat ? (v) => tickFormat(v) : undefined
|
||||
}
|
||||
tickLine={false}
|
||||
/>
|
||||
{showZeroLine ? (
|
||||
<ReferenceLine
|
||||
y={0}
|
||||
stroke="var(--fgd-4)"
|
||||
strokeDasharray="2 2"
|
||||
/>
|
||||
) : null}
|
||||
</AreaChart>
|
||||
) : (
|
||||
<BarChart
|
||||
data={filteredData}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<RechartsTooltip
|
||||
cursor={{
|
||||
fill: 'var(--bkg-2)',
|
||||
opacity: 0.5,
|
||||
}}
|
||||
content={customTooltip ? 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={yKey}>
|
||||
{filteredData.map((entry, index) => {
|
||||
return (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill={
|
||||
entry[yKey] > 0
|
||||
? 'url(#greenGradientBar)'
|
||||
: 'url(#redGradientBar)'
|
||||
}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Bar>
|
||||
<XAxis
|
||||
dataKey={xKey}
|
||||
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={yKey}
|
||||
interval="preserveStartEnd"
|
||||
axisLine={false}
|
||||
dx={-10}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill: 'var(--fgd-4)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
tickFormatter={
|
||||
tickFormat ? (v) => tickFormat(v) : undefined
|
||||
}
|
||||
type="number"
|
||||
/>
|
||||
<ReferenceLine y={0} stroke={COLORS.BKG4[theme]} />
|
||||
</BarChart>
|
||||
)}
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={`flex ${
|
||||
heightClass ? heightClass : 'h-96'
|
||||
} items-center justify-center p-4 text-th-fgd-3`}
|
||||
>
|
||||
<div>
|
||||
<NoSymbolIcon className="mx-auto mb-1 h-6 w-6 text-th-fgd-4" />
|
||||
<p className="text-th-fgd-4">{t('chart-unavailable')}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</ContentBox>
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"new-version": "New version available",
|
||||
"nft-market": "NFT Market",
|
||||
"no": "No",
|
||||
"no-data": "No data to display",
|
||||
"offchain-services": "Offchain Services",
|
||||
"open-account": "Open New Account",
|
||||
"operational": "Operational",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"new-version": "New version available",
|
||||
"nft-market": "NFT Market",
|
||||
"no": "No",
|
||||
"no-data": "No data to display",
|
||||
"offchain-services": "Offchain Services",
|
||||
"open-account": "Open New Account",
|
||||
"operational": "Operational",
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
"new-version": "New version available",
|
||||
"nft-market": "NFT Market",
|
||||
"no": "No",
|
||||
"no-data": "No data to display",
|
||||
"offchain-services": "Offchain Services",
|
||||
"open-account": "Open New Account",
|
||||
"operational": "Operational",
|
||||
|
|
|
@ -128,6 +128,7 @@
|
|||
"new-version": "新版本出来了",
|
||||
"nft-market": "NFT Market",
|
||||
"no": "不",
|
||||
"no-data": "无数据可显示",
|
||||
"offchain-services": "区块联外的服务",
|
||||
"open-account": "Open New Account",
|
||||
"operational": "运行中",
|
||||
|
|
|
@ -128,6 +128,7 @@
|
|||
"new-version": "新版本出來了",
|
||||
"nft-market": "NFT Market",
|
||||
"no": "不",
|
||||
"no-data": "無數據可顯示",
|
||||
"offchain-services": "區塊聯外的服務",
|
||||
"open-account": "Open New Account",
|
||||
"operational": "運行中",
|
||||
|
|
Loading…
Reference in New Issue