Commit 49f1acb5 authored by Brendan Wong's avatar Brendan Wong Committed by GitHub

fix: displays price when not updated on TDP (#7068)

* Update PriceChart.tsx

* simplify deltaarrow function

* update text coloring

* increase gap a bit more

* rename tags

* restyling of information

* fix import issue

* Update src/components/Tokens/TokenDetails/PriceChart.tsx
Co-authored-by: default avatarJordan Frankfurt <jordanwfrankfurt@gmail.com>

* unit testing!

---------
Co-authored-by: default avatarJordan Frankfurt <jordanwfrankfurt@gmail.com>
parent a97005e2
import { TimePeriod } from 'graphql/data/util'
import { render } from 'test-utils/render'
import { PriceChart } from './PriceChart'
jest.mock('components/Charts/AnimatedInLineChart', () => ({
__esModule: true,
default: jest.fn(() => null),
}))
jest.mock('components/Charts/FadeInLineChart', () => ({
__esModule: true,
default: jest.fn(() => null),
}))
describe('PriceChart', () => {
it('renders correctly with all prices filled', () => {
const mockPrices = Array.from({ length: 13 }, (_, i) => ({
value: 1,
timestamp: i * 3600,
}))
const { asFragment } = render(
<PriceChart prices={mockPrices} width={780} height={436} timePeriod={TimePeriod.HOUR} />
)
expect(asFragment()).toMatchSnapshot()
expect(asFragment().textContent).toContain('$1.00')
expect(asFragment().textContent).toContain('0.00%')
})
it('renders correctly with some prices filled', () => {
const mockPrices = Array.from({ length: 13 }, (_, i) => ({
value: i < 10 ? 1 : 0,
timestamp: i * 3600,
}))
const { asFragment } = render(
<PriceChart prices={mockPrices} width={780} height={436} timePeriod={TimePeriod.HOUR} />
)
expect(asFragment()).toMatchSnapshot()
expect(asFragment().textContent).toContain('$1.00')
expect(asFragment().textContent).toContain('0.00%')
})
it('renders correctly with no prices filled', () => {
const { asFragment } = render(<PriceChart prices={[]} width={780} height={436} timePeriod={TimePeriod.HOUR} />)
expect(asFragment()).toMatchSnapshot()
expect(asFragment().textContent).toContain('Price Unavailable')
})
})
......@@ -6,12 +6,13 @@ import { GlyphCircle } from '@visx/glyph'
import { Line } from '@visx/shape'
import AnimatedInLineChart from 'components/Charts/AnimatedInLineChart'
import FadedInLineChart from 'components/Charts/FadeInLineChart'
import { MouseoverTooltip } from 'components/Tooltip'
import { bisect, curveCardinal, NumberValue, scaleLinear, timeDay, timeHour, timeMinute, timeMonth } from 'd3'
import { PricePoint } from 'graphql/data/util'
import { TimePeriod } from 'graphql/data/util'
import { useActiveLocale } from 'hooks/useActiveLocale'
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
import { ArrowDownRight, ArrowUpRight, TrendingUp } from 'react-feather'
import { ArrowDownRight, ArrowUpRight, Info, TrendingUp } from 'react-feather'
import styled, { useTheme } from 'styled-components'
import { ThemedText } from 'theme'
import { textFadeIn } from 'theme/styles'
......@@ -41,18 +42,33 @@ const StyledDownArrow = styled(ArrowDownRight)`
color: ${({ theme }) => theme.accentFailure};
`
const DefaultUpArrow = styled(ArrowUpRight)`
color: ${({ theme }) => theme.textTertiary};
`
const DefaultDownArrow = styled(ArrowDownRight)`
color: ${({ theme }) => theme.textTertiary};
`
function calculateDelta(start: number, current: number) {
return (current / start - 1) * 100
}
export function getDeltaArrow(delta: number | null | undefined, iconSize = 20) {
export function getDeltaArrow(delta: number | null | undefined, iconSize = 20, styled = true) {
// Null-check not including zero
if (delta === null || delta === undefined) {
return null
} else if (Math.sign(delta) < 0) {
return <StyledDownArrow size={iconSize} key="arrow-down" aria-label="down" />
return styled ? (
<StyledDownArrow size={iconSize} key="arrow-down" aria-label="down" />
) : (
<DefaultDownArrow size={iconSize} key="arrow-down" aria-label="down" />
)
}
return <StyledUpArrow size={iconSize} key="arrow-up" aria-label="up" />
return styled ? (
<StyledUpArrow size={iconSize} key="arrow-up" aria-label="up" />
) : (
<DefaultUpArrow size={iconSize} key="arrow-up" aria-label="up" />
)
}
export function formatDelta(delta: number | null | undefined) {
......@@ -84,6 +100,10 @@ const MissingPrice = styled(TokenPrice)`
color: ${({ theme }) => theme.textTertiary};
`
const OutdatedContainer = styled.div`
color: ${({ theme }) => theme.textSecondary};
`
const DeltaContainer = styled.div`
height: 16px;
display: flex;
......@@ -95,6 +115,13 @@ export const ArrowCell = styled.div`
display: flex;
`
const OutdatedPriceContainer = styled.div`
display: flex;
gap: 6px;
font-size: 24px;
line-height: 44px;
`
function fixChart(prices: PricePoint[] | undefined | null) {
if (!prices) return { prices: null, blanks: [] }
......@@ -148,6 +175,34 @@ export function PriceChart({ width, height, prices: originalPrices, timePeriod }
)
) : null
const tooltipMessage = (
<>
<Trans>This price may not be up-to-date due to low trading volume.</Trans>
</>
)
//get the last non-zero price point
const lastPrice = useMemo(() => {
if (!prices) return DATA_EMPTY
for (let i = prices.length - 1; i >= 0; i--) {
if (prices[i].value !== 0) return prices[i]
}
return DATA_EMPTY
}, [prices])
//get the first non-zero price point
const firstPrice = useMemo(() => {
if (!prices) return DATA_EMPTY
for (let i = 0; i < prices.length; i++) {
if (prices[i].value !== 0) return prices[i]
}
return DATA_EMPTY
}, [prices])
const totalDelta = calculateDelta(firstPrice.value, lastPrice.value)
const formattedTotalDelta = formatDelta(totalDelta)
const defaultArrow = getDeltaArrow(totalDelta, 20, false)
// first price point on the x-axis of the current time period's chart
const startingPrice = originalPrices?.[0] ?? DATA_EMPTY
// last price point on the x-axis of the current time period's chart
......@@ -302,6 +357,19 @@ export function PriceChart({ width, height, prices: originalPrices, timePeriod }
<ArrowCell>{arrow}</ArrowCell>
</DeltaContainer>
</>
) : lastPrice.value ? (
<OutdatedContainer>
<OutdatedPriceContainer>
<TokenPrice>{formatUSDPrice(lastPrice.value)}</TokenPrice>
<MouseoverTooltip text={tooltipMessage}>
<Info size={16} />
</MouseoverTooltip>
</OutdatedPriceContainer>
<DeltaContainer>
{formattedTotalDelta}
<ArrowCell>{defaultArrow}</ArrowCell>
</DeltaContainer>
</OutdatedContainer>
) : (
<>
<MissingPrice>Price Unavailable</MissingPrice>
......
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