1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00
Norbi 31ee1aab98
Pool statistics graph shows two sets of data when switching tabs (#696)
* removed compose previous data with new data

* removed unused states

* fix refetch multiple times for same block number

Co-authored-by: Norbi <katunanorbert@gmai.com>
2021-06-25 10:34:39 +02:00

236 lines
6.4 KiB
TypeScript

/* eslint-disable camelcase */
import React, { ChangeEvent, ReactElement, useEffect, useState } from 'react'
import { Line, defaults } from 'react-chartjs-2'
import {
ChartData,
ChartDataSets,
ChartOptions,
ChartTooltipItem,
ChartTooltipOptions
} from 'chart.js'
import styles from './Graph.module.css'
import Loader from '../../../atoms/Loader'
import { formatPrice } from '../../../atoms/Price/PriceUnit'
import { useUserPreferences } from '../../../../providers/UserPreferences'
import useDarkMode from 'use-dark-mode'
import { darkModeConfig } from '../../../../../app.config'
import Button from '../../../atoms/Button'
import { Logger } from '@oceanprotocol/lib'
import { useAsset } from '../../../../providers/Asset'
import { gql, useQuery } from '@apollo/client'
import { PoolHistory } from '../../../../@types/apollo/PoolHistory'
declare type GraphType = 'liquidity' | 'price'
// Chart.js global defaults
defaults.global.defaultFontFamily = `'Sharp Sans', -apple-system, BlinkMacSystemFont,
'Segoe UI', Helvetica, Arial, sans-serif`
defaults.global.animation = { easing: 'easeInOutQuart', duration: 1000 }
const lineStyle: Partial<ChartDataSets> = {
fill: false,
lineTension: 0.1,
borderWidth: 2,
pointBorderWidth: 0,
pointRadius: 0,
pointHoverRadius: 4,
pointHoverBorderWidth: 0,
pointHitRadius: 2,
pointHoverBackgroundColor: '#ff4092'
}
const tooltipOptions: Partial<ChartTooltipOptions> = {
intersect: false,
titleFontStyle: 'normal',
titleFontSize: 10,
bodyFontSize: 12,
bodyFontStyle: 'bold',
displayColors: false,
xPadding: 10,
yPadding: 10,
cornerRadius: 3,
borderWidth: 1,
caretSize: 7
}
function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
return {
layout: {
padding: {
left: 0,
right: 0,
top: 0,
bottom: 10
}
},
tooltips: {
...tooltipOptions,
backgroundColor: isDarkMode ? `#141414` : `#fff`,
titleFontColor: isDarkMode ? `#e2e2e2` : `#303030`,
bodyFontColor: isDarkMode ? `#fff` : `#141414`,
borderColor: isDarkMode ? `#41474e` : `#e2e2e2`,
callbacks: {
label: (tooltipItem: ChartTooltipItem) =>
`${formatPrice(`${tooltipItem.yLabel}`, locale)} OCEAN`
}
},
legend: {
display: false
},
hover: {
intersect: false,
animationDuration: 0
},
scales: {
yAxes: [
{
display: false
// gridLines: {
// drawBorder: false,
// color: isDarkMode ? '#303030' : '#e2e2e2',
// zeroLineColor: isDarkMode ? '#303030' : '#e2e2e2'
// },
// ticks: { display: false }
}
],
xAxes: [{ display: false, gridLines: { display: true } }]
}
}
}
const graphTypes = ['Liquidity', 'Price']
const poolHistory = gql`
query PoolHistory($id: String!, $block: Int) {
poolTransactions(
first: 1000
where: { poolAddress: $id, block_gt: $block }
orderBy: block
) {
block
spotPrice
timestamp
oceanReserve
}
}
`
export default function Graph(): ReactElement {
const { locale } = useUserPreferences()
const darkMode = useDarkMode(false, darkModeConfig)
const [options, setOptions] = useState<ChartOptions>()
const [graphType, setGraphType] = useState<GraphType>('liquidity')
const { price } = useAsset()
const [lastBlock, setLastBlock] = useState<number>(0)
const [priceHistory, setPriceHistory] = useState([])
const [liquidityHistory, setLiquidityHistory] = useState([])
const [timestamps, setTimestamps] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [graphData, setGraphData] = useState<ChartData>()
const { data, refetch, error } = useQuery<PoolHistory>(poolHistory, {
variables: {
id: price.address.toLowerCase(),
block: lastBlock
},
pollInterval: 20000
})
useEffect(() => {
Logger.log('Fired GraphOptions!')
const options = getOptions(locale, darkMode.value)
setOptions(options)
}, [locale, darkMode.value])
useEffect(() => {
if (!data) return
Logger.log('Fired GraphData!')
const latestTimestamps = [
...timestamps,
...data.poolTransactions.map((item) => {
const date = new Date(item.timestamp * 1000)
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
})
]
setTimestamps(latestTimestamps)
const latestLiquidtyHistory = [
...liquidityHistory,
...data.poolTransactions.map((item) => item.oceanReserve)
]
setLiquidityHistory(latestLiquidtyHistory)
const latestPriceHistory = [
...priceHistory,
...data.poolTransactions.map((item) => item.spotPrice)
]
setPriceHistory(latestPriceHistory)
if (data.poolTransactions.length > 0) {
const newBlock =
data.poolTransactions[data.poolTransactions.length - 1].block
if (newBlock === lastBlock) return
setLastBlock(
data.poolTransactions[data.poolTransactions.length - 1].block
)
refetch()
} else {
setGraphData({
labels: latestTimestamps.slice(0),
datasets: [
{
...lineStyle,
label: 'Liquidity (OCEAN)',
data:
graphType === 'liquidity'
? latestLiquidtyHistory.slice(0)
: latestPriceHistory.slice(0),
borderColor: `#8b98a9`,
pointBackgroundColor: `#8b98a9`
}
]
})
setIsLoading(false)
}
}, [data, graphType])
function handleGraphTypeSwitch(e: ChangeEvent<HTMLButtonElement>) {
e.preventDefault()
setGraphType(e.currentTarget.textContent.toLowerCase() as GraphType)
}
return (
<div className={styles.graphWrap}>
{isLoading ? (
<Loader />
) : error ? (
<small>{error.message}</small>
) : (
<>
<nav className={styles.type}>
{graphTypes.map((type: GraphType) => (
<Button
key={type}
style="text"
size="small"
onClick={handleGraphTypeSwitch}
className={`${styles.button} ${
graphType === type.toLowerCase() ? styles.active : null
}`}
>
{type}
</Button>
))}
</nav>
<Line height={70} data={graphData} options={options} />
</>
)}
</div>
)
}