Commit f161f961 authored by lynn's avatar lynn Committed by GitHub

feat: Web 924 explore use real data for the sparkline price charts (#4634)

* init

* test

* working w new hook

* simsplify

* fixes to comments

* extra comment remove
parent 9d3249e6
import { curveCardinalOpen, scaleLinear } from 'd3' import { curveCardinal, scaleLinear } from 'd3'
import { SingleTokenData, TimePeriod, useTokenPricesFromFragment } from 'graphql/data/Token'
import React from 'react' import React from 'react'
import { useTheme } from 'styled-components/macro' import { useTheme } from 'styled-components/macro'
import data from './data.json' import { DATA_EMPTY, getPriceBounds } from '../Tokens/TokenDetails/PriceChart'
import LineChart from './LineChart' import LineChart from './LineChart'
type PricePoint = { value: number; timestamp: number } type PricePoint = { value: number; timestamp: number }
function getPriceBounds(pricePoints: PricePoint[]): [number, number] {
const prices = pricePoints.map((x) => x.value)
const min = Math.min(...prices)
const max = Math.max(...prices)
return [min, max]
}
interface SparklineChartProps { interface SparklineChartProps {
width: number width: number
height: number height: number
tokenData: SingleTokenData
pricePercentChange: number | undefined | null
timePeriod: TimePeriod
} }
function SparklineChart({ width, height }: SparklineChartProps) { function SparklineChart({ width, height, tokenData, pricePercentChange, timePeriod }: SparklineChartProps) {
const theme = useTheme() const theme = useTheme()
// for sparkline
const pricePoints = useTokenPricesFromFragment(tokenData?.prices?.[0]) ?? []
const hasData = pricePoints.length !== 0
const startingPrice = hasData ? pricePoints[0] : DATA_EMPTY
const endingPrice = hasData ? pricePoints[pricePoints.length - 1] : DATA_EMPTY
const widthScale = scaleLinear().domain([startingPrice.timestamp, endingPrice.timestamp]).range([0, 124])
const rdScale = scaleLinear().domain(getPriceBounds(pricePoints)).range([42, 0])
/* TODO: Implement API calls & cache to use here */ /* Default curve doesn't look good for the ALL chart */
const pricePoints = data.day const curveTension = timePeriod === TimePeriod.ALL ? 0.75 : 0.9
const startingPrice = pricePoints[0]
const endingPrice = pricePoints[pricePoints.length - 1]
const timeScale = scaleLinear().domain([startingPrice.timestamp, endingPrice.timestamp]).range([0, width])
const rdScale = scaleLinear().domain(getPriceBounds(pricePoints)).range([height, 0])
const isPositive = endingPrice.value >= startingPrice.value
return ( return (
<LineChart <LineChart
data={pricePoints} data={pricePoints}
getX={(p: PricePoint) => timeScale(p.timestamp)} getX={(p: PricePoint) => widthScale(p.timestamp)}
getY={(p: PricePoint) => rdScale(p.value)} getY={(p: PricePoint) => rdScale(p.value)}
curve={curveCardinalOpen.tension(0.9)} curve={curveCardinal.tension(curveTension)}
marginTop={0} color={pricePercentChange && pricePercentChange < 0 ? theme.accentFailure : theme.accentSuccess}
color={isPositive ? theme.accentSuccess : theme.accentFailure}
strokeWidth={1.5} strokeWidth={1.5}
width={width} width={width}
height={height} height={height}
></LineChart> />
) )
} }
......
...@@ -30,7 +30,7 @@ import { DISPLAYS, ORDERED_TIMES } from '../TokenTable/TimeSelector' ...@@ -30,7 +30,7 @@ import { DISPLAYS, ORDERED_TIMES } from '../TokenTable/TimeSelector'
export const DATA_EMPTY = { value: 0, timestamp: 0 } export const DATA_EMPTY = { value: 0, timestamp: 0 }
function getPriceBounds(pricePoints: PricePoint[]): [number, number] { export function getPriceBounds(pricePoints: PricePoint[]): [number, number] {
const prices = pricePoints.map((x) => x.value) const prices = pricePoints.map((x) => x.value)
const min = Math.min(...prices) const min = Math.min(...prices)
const max = Math.max(...prices) const max = Math.max(...prices)
......
...@@ -5,8 +5,7 @@ import { EventName } from 'components/AmplitudeAnalytics/constants' ...@@ -5,8 +5,7 @@ import { EventName } from 'components/AmplitudeAnalytics/constants'
import SparklineChart from 'components/Charts/SparklineChart' import SparklineChart from 'components/Charts/SparklineChart'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/CurrencyLogo'
import { getChainInfo } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { getDurationDetails, SingleTokenData } from 'graphql/data/Token' import { getDurationDetails, SingleTokenData, TimePeriod } from 'graphql/data/Token'
import { TimePeriod } from 'graphql/data/Token'
import { useCurrency } from 'hooks/Tokens' import { useCurrency } from 'hooks/Tokens'
import { useAtomValue } from 'jotai/utils' import { useAtomValue } from 'jotai/utils'
import { ReactNode } from 'react' import { ReactNode } from 'react'
...@@ -543,7 +542,17 @@ export default function LoadedRow({ ...@@ -543,7 +542,17 @@ export default function LoadedRow({
volume={<ClickableContent>{volume ? formatDollarAmount(volume ?? undefined) : '-'}</ClickableContent>} volume={<ClickableContent>{volume ? formatDollarAmount(volume ?? undefined) : '-'}</ClickableContent>}
sparkLine={ sparkLine={
<SparkLine> <SparkLine>
<ParentSize>{({ width, height }) => <SparklineChart width={width} height={height} />}</ParentSize> <ParentSize>
{({ width, height }) => (
<SparklineChart
width={width}
height={height}
tokenData={tokenData}
pricePercentChange={pricePercentChange}
timePeriod={timePeriod}
/>
)}
</ParentSize>
</SparkLine> </SparkLine>
} }
first={tokenListIndex === 0} first={tokenListIndex === 0}
......
...@@ -257,10 +257,15 @@ const tokenPriceQuery = graphql` ...@@ -257,10 +257,15 @@ const tokenPriceQuery = graphql`
} }
` `
function filterPrices(prices: TokenPrices$data['priceHistory'] | undefined) { export function filterPrices(prices: TokenPrices$data['priceHistory'] | undefined) {
return prices?.filter((p): p is PricePoint => Boolean(p && p.value)) return prices?.filter((p): p is PricePoint => Boolean(p && p.value))
} }
export function useTokenPricesFromFragment(key: TokenPrices$key | null | undefined) {
const fetchedTokenPrices = useFragment(tokenPricesFragment, key ?? null)?.priceHistory
return filterPrices(fetchedTokenPrices)
}
export function useTokenPricesCached( export function useTokenPricesCached(
key: TokenPrices$key | null | undefined, key: TokenPrices$key | null | undefined,
address: string, address: string,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment