stacker.news/components/price.js

135 lines
3.4 KiB
JavaScript
Raw Normal View History

import React, { useContext, useEffect, useMemo, useState } from 'react'
import { useQuery } from '@apollo/client'
import { fixedDecimal } from '@/lib/format'
2022-09-12 23:42:09 +00:00
import { useMe } from './me'
import { PRICE } from '@/fragments/price'
import { CURRENCY_SYMBOLS } from '@/lib/currency'
import { NORMAL_POLL_INTERVAL, SSR } from '@/lib/constants'
import { useBlockHeight } from './block-height'
import { useChainFee } from './chain-fee'
2024-04-16 22:58:26 +00:00
import { CompactLongCountdown } from './countdown'
2021-04-12 18:05:09 +00:00
2021-11-28 17:29:17 +00:00
export const PriceContext = React.createContext({
price: null,
fiatSymbol: null
2021-11-28 17:29:17 +00:00
})
export function usePrice () {
return useContext(PriceContext)
2021-11-28 17:29:17 +00:00
}
export function PriceProvider ({ price, children }) {
2022-09-18 01:07:14 +00:00
const me = useMe()
const fiatCurrency = me?.privates?.fiatCurrency
const { data } = useQuery(PRICE, {
variables: { fiatCurrency },
...(SSR
? {}
: {
pollInterval: NORMAL_POLL_INTERVAL,
nextFetchPolicy: 'cache-and-network'
})
})
2021-04-12 18:05:09 +00:00
const contextValue = useMemo(() => ({
price: data?.price || price,
fiatSymbol: CURRENCY_SYMBOLS[fiatCurrency] || '$'
}), [data?.price, price, me?.privates?.fiatCurrency])
2021-11-28 17:29:17 +00:00
return (
<PriceContext.Provider value={contextValue}>
{children}
</PriceContext.Provider>
)
}
const STORAGE_KEY = 'asSats'
const DEFAULT_SELECTION = 'fiat'
const carousel = [
'fiat',
'yep',
'1btc',
'blockHeight',
'chainFee',
'halving'
]
2023-05-01 20:58:30 +00:00
export default function Price ({ className }) {
2021-11-28 17:29:17 +00:00
const [asSats, setAsSats] = useState(undefined)
const [pos, setPos] = useState(0)
useEffect(() => {
const selection = window.localStorage.getItem(STORAGE_KEY) ?? DEFAULT_SELECTION
setAsSats(selection)
setPos(carousel.findIndex((item) => item === selection))
2021-11-28 17:29:17 +00:00
}, [])
const { price, fiatSymbol } = usePrice()
2024-04-16 22:58:26 +00:00
const { height: blockHeight, halving } = useBlockHeight()
const { fee: chainFee } = useChainFee()
2021-04-29 18:43:17 +00:00
const handleClick = () => {
const nextPos = (pos + 1) % carousel.length
window.localStorage.setItem(STORAGE_KEY, carousel[nextPos])
setAsSats(carousel[nextPos])
setPos(nextPos)
2021-04-29 18:43:17 +00:00
}
2023-05-01 20:58:30 +00:00
const compClassName = (className || '') + ' text-reset pointer'
2021-12-05 17:37:55 +00:00
if (asSats === 'yep') {
2024-04-16 22:58:26 +00:00
if (!price || price < 0) return null
2021-04-29 15:56:28 +00:00
return (
2023-05-01 20:58:30 +00:00
<div className={compClassName} onClick={handleClick} variant='link'>
2022-09-12 23:42:09 +00:00
{fixedDecimal(100000000 / price, 0) + ` sats/${fiatSymbol}`}
2023-05-01 20:58:30 +00:00
</div>
2021-04-29 15:56:28 +00:00
)
}
2021-12-05 17:37:55 +00:00
if (asSats === '1btc') {
return (
2023-05-01 20:58:30 +00:00
<div className={compClassName} onClick={handleClick} variant='link'>
2021-12-05 17:37:55 +00:00
1sat=1sat
2023-05-01 20:58:30 +00:00
</div>
2021-12-05 17:37:55 +00:00
)
}
if (asSats === 'blockHeight') {
2024-04-16 22:58:26 +00:00
if (blockHeight <= 0) return null
return (
<div className={compClassName} onClick={handleClick} variant='link'>
2023-09-12 21:36:26 +00:00
{blockHeight}
</div>
)
}
2024-04-16 22:58:26 +00:00
if (asSats === 'halving') {
if (!halving) return null
return (
<div className={compClassName} onClick={handleClick} variant='link'>
<CompactLongCountdown date={halving} />
</div>
)
}
if (asSats === 'chainFee') {
2024-04-16 22:58:26 +00:00
if (chainFee <= 0) return null
return (
<div className={compClassName} onClick={handleClick} variant='link'>
{chainFee} sat/vB
</div>
)
}
if (asSats === 'fiat') {
2024-04-16 22:58:26 +00:00
if (!price || price < 0) return null
return (
<div className={compClassName} onClick={handleClick} variant='link'>
{fiatSymbol + fixedDecimal(price, 0)}
</div>
)
}
2021-04-12 18:05:09 +00:00
}