add placeholder account value chart
This commit is contained in:
parent
2391755ea9
commit
210e96237d
|
@ -0,0 +1,281 @@
|
|||
import { FunctionComponent, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import {
|
||||
AreaChart,
|
||||
Area,
|
||||
XAxis,
|
||||
YAxis,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts'
|
||||
import FlipNumbers from 'react-flip-numbers'
|
||||
|
||||
import LineChartIcon from '../icons/LineChartIcon'
|
||||
import ContentBox from '../shared/ContentBox'
|
||||
import { DownTriangle, UpTriangle } from '../shared/DirectionTriangles'
|
||||
import { formatFixedDecimals } from '../../utils/numbers'
|
||||
import SheenLoader from '../shared/SheenLoader'
|
||||
import { COLORS } from '../../styles/colors'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { IconButton } from './Button'
|
||||
import { ArrowLeftIcon } from '@heroicons/react/solid'
|
||||
import { FadeInFadeOut } from './Transitions'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
interface DetailedAreaChartProps {
|
||||
data: any[]
|
||||
hideChart?: () => void
|
||||
loading?: boolean
|
||||
title?: string
|
||||
xKey: string
|
||||
yKey: string
|
||||
}
|
||||
|
||||
const DetailedAreaChart: FunctionComponent<DetailedAreaChartProps> = ({
|
||||
data,
|
||||
hideChart,
|
||||
loading,
|
||||
title,
|
||||
xKey,
|
||||
yKey,
|
||||
}) => {
|
||||
const [mouseData, setMouseData] = useState<any>(null)
|
||||
const [daysToShow, setDaysToShow] = useState(1)
|
||||
const { theme } = useTheme()
|
||||
|
||||
const handleMouseMove = (coords: any) => {
|
||||
if (coords.activePayload) {
|
||||
setMouseData(coords.activePayload[0].payload)
|
||||
}
|
||||
}
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setMouseData(null)
|
||||
}
|
||||
|
||||
const calculateChartChange = () => {
|
||||
if (data.length) {
|
||||
if (mouseData) {
|
||||
const index = data.findIndex((d: any) => d[xKey] === mouseData[xKey])
|
||||
return ((data[index][yKey] - data[0][yKey]) / data[0][yKey]) * 100
|
||||
} else
|
||||
return (
|
||||
((data[data.length - 1][yKey] - data[0][yKey]) / data[0][yKey]) * 100
|
||||
)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
return (
|
||||
<FadeInFadeOut show={true}>
|
||||
<ContentBox hideBorder hidePadding>
|
||||
{loading ? (
|
||||
<SheenLoader>
|
||||
<div className="h-[448px] rounded-lg bg-th-bkg-2" />
|
||||
</SheenLoader>
|
||||
) : data.length ? (
|
||||
<div className="relative">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex flex-col md:flex-row md:items-start md:space-x-6">
|
||||
<IconButton className="mb-6" onClick={hideChart}>
|
||||
<ArrowLeftIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
<div>
|
||||
<p className="mb-0.5 text-base text-th-fgd-3">{title}</p>
|
||||
{mouseData ? (
|
||||
<div>
|
||||
<div className="mb-1 flex items-end text-4xl font-bold text-th-fgd-1">
|
||||
<FlipNumbers
|
||||
height={40}
|
||||
width={26}
|
||||
play
|
||||
numbers={formatFixedDecimals(mouseData[yKey])}
|
||||
/>
|
||||
<span
|
||||
className={`ml-3 flex items-center text-sm ${
|
||||
calculateChartChange() >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{calculateChartChange() >= 0 ? (
|
||||
<UpTriangle />
|
||||
) : (
|
||||
<DownTriangle />
|
||||
)}
|
||||
<span className="ml-1">
|
||||
{calculateChartChange().toFixed(2)}%
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-th-fgd-4">
|
||||
{dayjs(mouseData[xKey]).format('DD MMM YY, h:mma')}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className="mb-1 flex items-end text-4xl font-bold text-th-fgd-1">
|
||||
<FlipNumbers
|
||||
height={40}
|
||||
width={26}
|
||||
play
|
||||
numbers={formatFixedDecimals(
|
||||
data[data.length - 1][yKey]
|
||||
)}
|
||||
/>
|
||||
<span
|
||||
className={`ml-3 mt-0 flex items-center text-sm ${
|
||||
calculateChartChange() >= 0
|
||||
? 'text-th-green'
|
||||
: 'text-th-red'
|
||||
}`}
|
||||
>
|
||||
{calculateChartChange() >= 0 ? (
|
||||
<UpTriangle />
|
||||
) : (
|
||||
<DownTriangle />
|
||||
)}
|
||||
<span className="ml-1">
|
||||
{calculateChartChange().toFixed(2)}%
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-th-fgd-4">
|
||||
{dayjs(data[data.length - 1][xKey]).format(
|
||||
'DD MMM YY, h:mma'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="-mt-1 h-96 w-auto">
|
||||
<div className="absolute -top-1 right-0 -mb-2 flex justify-end">
|
||||
<button
|
||||
className={`rounded-md px-3 py-2 font-bold text-th-fgd-4 focus:outline-none md:hover:text-th-primary ${
|
||||
daysToShow === 1 && 'text-th-primary'
|
||||
}`}
|
||||
onClick={() => setDaysToShow(1)}
|
||||
>
|
||||
24H
|
||||
</button>
|
||||
<button
|
||||
className={`rounded-md px-3 py-2 font-bold text-th-fgd-4 focus:outline-none md:hover:text-th-primary ${
|
||||
daysToShow === 7 && 'text-th-primary'
|
||||
}`}
|
||||
onClick={() => setDaysToShow(7)}
|
||||
>
|
||||
7D
|
||||
</button>
|
||||
<button
|
||||
className={`rounded-md px-3 py-2 font-bold text-th-fgd-4 focus:outline-none md:hover:text-th-primary ${
|
||||
daysToShow === 30 && 'text-th-primary'
|
||||
}`}
|
||||
onClick={() => setDaysToShow(30)}
|
||||
>
|
||||
30D
|
||||
</button>
|
||||
</div>
|
||||
<div className="-mx-6 mt-6 h-full">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart
|
||||
data={data}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<Tooltip
|
||||
cursor={{
|
||||
strokeOpacity: 0.09,
|
||||
}}
|
||||
content={<></>}
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id="gradientArea"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="0"
|
||||
y2="1"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stopColor={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.GREEN[theme]
|
||||
: COLORS.RED[theme]
|
||||
}
|
||||
stopOpacity={0.15}
|
||||
/>
|
||||
<stop
|
||||
offset="99%"
|
||||
stopColor={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.GREEN[theme]
|
||||
: COLORS.RED[theme]
|
||||
}
|
||||
stopOpacity={0}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<Area
|
||||
isAnimationActive={false}
|
||||
type="monotone"
|
||||
dataKey={yKey}
|
||||
stroke={
|
||||
calculateChartChange() >= 0
|
||||
? COLORS.GREEN[theme]
|
||||
: COLORS.RED[theme]
|
||||
}
|
||||
strokeWidth={1.5}
|
||||
fill="url(#gradientArea)"
|
||||
/>
|
||||
<XAxis
|
||||
axisLine={false}
|
||||
dataKey={xKey}
|
||||
padding={{ left: 20, right: 20 }}
|
||||
tick={{
|
||||
fill:
|
||||
theme === 'Light'
|
||||
? 'rgba(0,0,0,0.4)'
|
||||
: 'rgba(255,255,255,0.6)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
axisLine={false}
|
||||
dataKey={yKey}
|
||||
type="number"
|
||||
domain={['dataMin', 'dataMax']}
|
||||
padding={{ top: 20, bottom: 20 }}
|
||||
tick={{
|
||||
fill:
|
||||
theme === 'Light'
|
||||
? 'rgba(0,0,0,0.4)'
|
||||
: 'rgba(255,255,255,0.6)',
|
||||
fontSize: 10,
|
||||
}}
|
||||
tickLine={false}
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-96 items-center justify-center rounded-lg bg-th-bkg-2 p-4 text-th-fgd-3">
|
||||
<div className="">
|
||||
<LineChartIcon className="mx-auto h-10 w-10 text-th-fgd-4" />
|
||||
<p className="text-th-fgd-4">Chart not available</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ContentBox>
|
||||
</FadeInFadeOut>
|
||||
)
|
||||
}
|
||||
|
||||
export default DetailedAreaChart
|
|
@ -10,6 +10,14 @@ import TokenList from '../components/TokenList'
|
|||
import mangoStore from '../store/state'
|
||||
import { formatDecimal } from '../utils/numbers'
|
||||
import FlipNumbers from 'react-flip-numbers'
|
||||
import { UpTriangle } from '../components/shared/DirectionTriangles'
|
||||
import SimpleAreaChart from '../components/shared/SimpleAreaChart'
|
||||
import { COLORS } from '../styles/colors'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { IconButton } from '../components/shared/Button'
|
||||
import { ArrowsExpandIcon } from '@heroicons/react/solid'
|
||||
import DetailedAreaChart from '../components/shared/DetailedAreaChart'
|
||||
import { Transition } from '@headlessui/react'
|
||||
|
||||
export async function getStaticProps({ locale }: { locale: string }) {
|
||||
return {
|
||||
|
@ -19,15 +27,46 @@ export async function getStaticProps({ locale }: { locale: string }) {
|
|||
}
|
||||
}
|
||||
|
||||
const chartData = [
|
||||
[1, 300],
|
||||
[2, 310],
|
||||
[3, 320],
|
||||
[4, 330],
|
||||
[5, 340],
|
||||
[6, 350],
|
||||
[7, 360],
|
||||
[8, 370],
|
||||
[9, 380],
|
||||
[10, 390],
|
||||
]
|
||||
|
||||
const Index: NextPage = () => {
|
||||
const { t } = useTranslation('common')
|
||||
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
|
||||
const [showDepositModal, setShowDepositModal] = useState(false)
|
||||
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
|
||||
const [showDetailedValueChart, setShowDetailedValueChart] = useState(false)
|
||||
const [showExpandChart, setShowExpandChart] = useState(false)
|
||||
const { theme } = useTheme()
|
||||
|
||||
return (
|
||||
const onHoverMenu = (open: boolean, action: string) => {
|
||||
if (
|
||||
(!open && action === 'onMouseEnter') ||
|
||||
(open && action === 'onMouseLeave')
|
||||
) {
|
||||
setShowExpandChart(!open)
|
||||
}
|
||||
}
|
||||
|
||||
const handleShowDetailedValueChart = () => {
|
||||
setShowDetailedValueChart(true)
|
||||
setShowExpandChart(false)
|
||||
}
|
||||
|
||||
return !showDetailedValueChart ? (
|
||||
<>
|
||||
<div className="mb-8 flex items-end justify-between border-b border-th-bkg-3 pb-8">
|
||||
<div className="mb-8 flex flex-col border-b border-th-bkg-3 pb-8 lg:flex-row lg:items-end lg:justify-between">
|
||||
<div className="mb-4 flex items-center space-x-6 lg:mb-0">
|
||||
<div>
|
||||
<p className="mb-1">{t('account-value')}</p>
|
||||
<div className="flex items-center text-5xl font-bold text-th-fgd-1">
|
||||
|
@ -48,15 +87,43 @@ const Index: NextPage = () => {
|
|||
(0).toFixed(2)
|
||||
)}
|
||||
</div>
|
||||
{/* <div className="text-5xl font-bold text-th-fgd-1">
|
||||
$
|
||||
{mangoAccount
|
||||
? formatDecimal(
|
||||
toUiDecimals(mangoAccount.getEquity().toNumber()),
|
||||
2
|
||||
)
|
||||
: (0).toFixed(2)}
|
||||
</div> */}
|
||||
<div className="mt-1 flex items-center space-x-2">
|
||||
<UpTriangle />
|
||||
<p className="mb-0.5 text-th-green">2.13%</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="relative flex items-end"
|
||||
onMouseEnter={() => onHoverMenu(showExpandChart, 'onMouseEnter')}
|
||||
onMouseLeave={() => onHoverMenu(showExpandChart, 'onMouseLeave')}
|
||||
>
|
||||
<SimpleAreaChart
|
||||
color={COLORS.GREEN[theme]}
|
||||
data={chartData}
|
||||
height={106}
|
||||
name="accountValue"
|
||||
width={240}
|
||||
/>
|
||||
<Transition
|
||||
appear={true}
|
||||
className="absolute right-2 bottom-2"
|
||||
show={showExpandChart}
|
||||
enter="transition-all ease-in duration-300"
|
||||
enterFrom="opacity-0 transform scale-75"
|
||||
enterTo="opacity-100 transform scale-100"
|
||||
leave="transition ease-out duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<IconButton
|
||||
className="text-th-fgd-3"
|
||||
hideBg
|
||||
onClick={() => handleShowDetailedValueChart()}
|
||||
>
|
||||
<ArrowsExpandIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
<AccountActions />
|
||||
</div>
|
||||
|
@ -74,6 +141,14 @@ const Index: NextPage = () => {
|
|||
/>
|
||||
) : null}
|
||||
</>
|
||||
) : (
|
||||
<DetailedAreaChart
|
||||
data={chartData}
|
||||
hideChart={() => setShowDetailedValueChart(false)}
|
||||
title={t('account-value')}
|
||||
xKey="0"
|
||||
yKey="1"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue