import { useEffect, useMemo, useState } from 'react'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import {
AreaChart,
Area,
XAxis,
YAxis,
Tooltip,
ResponsiveContainer,
Text,
} from 'recharts'
import FlipNumbers from 'react-flip-numbers'
import LineChartIcon from '../icons/LineChartIcon'
import ContentBox from '../shared/ContentBox'
import { formatFixedDecimals } from '../../utils/numbers'
import SheenLoader from '../shared/SheenLoader'
import { COLORS } from '../../styles/colors'
import { useTheme } from 'next-themes'
import Change from '../shared/Change'
import ChartRangeButtons from '../shared/ChartRangeButtons'
import { useViewport } from 'hooks/useViewport'
import { formatTokenSymbol } from 'utils/tokens'
import { useQuery } from '@tanstack/react-query'
import { fetchChartData } from 'apis/coingecko'
import mangoStore from '@store/mangoStore'
import useJupiterSwapData from './useJupiterSwapData'
import useLocalStorageState from 'hooks/useLocalStorageState'
import { ANIMATION_SETTINGS_KEY } from 'utils/constants'
import { INITIAL_ANIMATION_SETTINGS } from '@components/settings/AnimationSettings'
dayjs.extend(relativeTime)
const CustomizedLabel = ({
chartData,
x,
y,
value,
}: {
chartData: any[]
x?: number
y?: string | number
value?: number
}) => {
const { width } = useViewport()
const [min, max] = useMemo(() => {
if (chartData.length) {
const prices = chartData.map((d: any) => d.price)
return [Math.min(...prices), Math.max(...prices)]
}
return ['', '']
}, [chartData])
if (value === min || value === max) {
return (
width / 3 ? 'end' : 'start'}
className="font-mono"
>
{formatFixedDecimals(value)}
)
} else return
}
const SwapTokenChart = () => {
const { inputBank, outputBank } = mangoStore((s) => s.swap)
const { inputCoingeckoId, outputCoingeckoId } = useJupiterSwapData()
const [baseTokenId, setBaseTokenId] = useState(inputCoingeckoId)
const [quoteTokenId, setQuoteTokenId] = useState(outputCoingeckoId)
const [mouseData, setMouseData] = useState(null)
const [daysToShow, setDaysToShow] = useState('1')
const { theme } = useTheme()
const [animationSettings] = useLocalStorageState(
ANIMATION_SETTINGS_KEY,
INITIAL_ANIMATION_SETTINGS
)
const chartDataQuery = useQuery(
['chart-data', baseTokenId, quoteTokenId, daysToShow],
() => fetchChartData(baseTokenId, quoteTokenId, daysToShow),
{
cacheTime: 1000 * 60 * 1,
staleTime: 1000 * 60 * 1,
enabled: !!baseTokenId && !!quoteTokenId,
}
)
const chartData = chartDataQuery.data
const handleMouseMove = (coords: any) => {
if (coords.activePayload) {
setMouseData(coords.activePayload[0].payload)
}
}
const handleMouseLeave = () => {
setMouseData(null)
}
useEffect(() => {
if (!inputCoingeckoId || !outputCoingeckoId) return
if (['usd-coin', 'tether'].includes(outputCoingeckoId)) {
setBaseTokenId(inputCoingeckoId)
setQuoteTokenId(outputCoingeckoId)
} else {
setBaseTokenId(outputCoingeckoId)
setQuoteTokenId(inputCoingeckoId)
}
}, [inputCoingeckoId, outputCoingeckoId])
// const handleFlipChart = useCallback(() => {
// if (!baseTokenId || !quoteTokenId) return
// setBaseTokenId(quoteTokenId)
// setQuoteTokenId(baseTokenId)
// }, [baseTokenId, quoteTokenId])
const calculateChartChange = () => {
if (chartData.length) {
if (mouseData) {
const index = chartData.findIndex((d: any) => d.time === mouseData.time)
return (
((chartData[index]['price'] - chartData[0]['price']) /
chartData[0]['price']) *
100
)
} else
return (
((chartData[chartData.length - 1]['price'] - chartData[0]['price']) /
chartData[0]['price']) *
100
)
}
return 0
}
return (
{chartDataQuery?.isLoading || chartDataQuery.isFetching ? (
<>
>
) : chartData?.length && baseTokenId && quoteTokenId ? (
{inputBank && outputBank ? (
{['usd-coin', 'tether'].includes(inputCoingeckoId || '')
? `${formatTokenSymbol(
outputBank?.name?.toUpperCase()
)}/${inputBank?.name?.toUpperCase()}`
: `${formatTokenSymbol(
inputBank?.name?.toUpperCase()
)}/${formatTokenSymbol(
outputBank?.name?.toUpperCase()
)}`}
{/*
*/}
) : null}
{mouseData ? (
<>
{animationSettings['number-scroll'] ? (
) : (
{formatFixedDecimals(mouseData['price'])}
)}
{dayjs(mouseData['time']).format('DD MMM YY, h:mma')}
>
) : (
<>
{animationSettings['number-scroll'] ? (
) : (
{formatFixedDecimals(
chartData[chartData.length - 1]['price']
)}
)}
{dayjs(chartData[chartData.length - 1]['time']).format(
'DD MMM YY, h:mma'
)}
>
)}
setDaysToShow(v)}
/>
>}
/>
= 0
? COLORS.UP[theme]
: COLORS.DOWN[theme]
}
stopOpacity={0.25}
/>
= 0
? COLORS.UP[theme]
: COLORS.DOWN[theme]
}
stopOpacity={0}
/>
= 0
? COLORS.UP[theme]
: COLORS.DOWN[theme]
}
strokeWidth={1.5}
fill="url(#gradientArea)"
label={}
/>
) : (
)}
)
}
export default SwapTokenChart