Skip to content
This repository has been archived by the owner on Oct 10, 2023. It is now read-only.

Commit

Permalink
Display APY/APR depending on days (#2477)
Browse files Browse the repository at this point in the history
- [x]  `setPoolsPeriod` / `poolsPeriod$`
- [x] Update pools/pools detail data handling to depend on selected `GetPoolsPeriodEnum`
- [x] `SelectPoolsPeriod` component (used in `ActivePoolsOverview`, `PoolsDetail`, `SaversOverview`)
- [x] Helper `poolsPeriodToPoolPeriod` incl. tests
- [x] Update `i18n`
  • Loading branch information
veado authored Dec 11, 2022
1 parent ea5c112 commit d2df617
Show file tree
Hide file tree
Showing 22 changed files with 382 additions and 71 deletions.
17 changes: 15 additions & 2 deletions src/renderer/components/pool/PoolCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import { ZERO_ASSET_AMOUNT, ZERO_BN } from '../../const'
import { sequenceTRD } from '../../helpers/fpHelpers'
import { abbreviateNumber } from '../../helpers/numberHelper'
import { PoolDetailRD, PoolStatsDetailRD } from '../../services/midgard/types'
import { GetPoolsPeriodEnum } from '../../types/generated/midgard'
import { ErrorView } from '../shared/error'
import { Button } from '../uielements/button'
import { PoolsPeriodSelector } from '../uielements/pools/PoolsPeriodSelector'
import { PoolStatus } from '../uielements/poolStatus'
import * as Styled from './PoolCards.styles'
import * as H from './PoolDetails.helpers'
Expand All @@ -22,10 +24,20 @@ export type Props = {
reloadData: FP.Lazy<void>
priceSymbol: string
priceRatio: BigNumber
poolsPeriod: GetPoolsPeriodEnum
setPoolsPeriod: (v: GetPoolsPeriodEnum) => void
}

export const PoolCards: React.FC<Props> = (props) => {
const { poolStatsDetail: poolStatsDetailRD, priceSymbol, poolDetail: poolDetailRD, priceRatio, reloadData } = props
const {
poolStatsDetail: poolStatsDetailRD,
priceSymbol,
poolDetail: poolDetailRD,
priceRatio,
reloadData,
poolsPeriod,
setPoolsPeriod
} = props
const intl = useIntl()

const getFullValue = useCallback(
Expand Down Expand Up @@ -112,6 +124,7 @@ export const PoolCards: React.FC<Props> = (props) => {
<PoolStatus
isLoading={isLoading}
label={intl.formatMessage({ id: 'deposit.poolDetails.apy' })}
extraLabel={<PoolsPeriodSelector selectedValue={poolsPeriod} onChange={setPoolsPeriod} />}
displayValue={`${abbreviateNumber(apy.toNumber(), 2)} %`}
/>
</Styled.Col>
Expand All @@ -126,7 +139,7 @@ export const PoolCards: React.FC<Props> = (props) => {
</Styled.Col>
</Styled.Container>
),
[getFullValue, intl, priceSymbol]
[getFullValue, intl, poolsPeriod, priceSymbol, setPoolsPeriod]
)

return FP.pipe(
Expand Down
14 changes: 8 additions & 6 deletions src/renderer/components/pool/PoolDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as FP from 'fp-ts/lib/function'

import { Network } from '../../../shared/api/types'
import { PoolDetailRD, PoolStatsDetailRD } from '../../services/midgard/types'
import { GetPoolsStatusEnum } from '../../types/generated/midgard'
import { GetPoolsPeriodEnum, GetPoolsStatusEnum } from '../../types/generated/midgard'
import { PoolHistoryActions } from '../../views/pool/PoolHistoryView.types'
import { PoolCards } from './PoolCards'
import * as H from './PoolDetails.helpers'
Expand All @@ -26,7 +26,6 @@ export type Props = {
reloadPoolDetail: FP.Lazy<void>
priceRatio: BigNumber
priceSymbol: string
isLoading?: boolean
HistoryView: React.ComponentType<{
poolAsset: Asset
historyActions: PoolHistoryActions
Expand All @@ -37,6 +36,8 @@ export type Props = {
disablePoolActions: boolean
walletLocked: boolean
network: Network
poolsPeriod: GetPoolsPeriodEnum
setPoolsPeriod: (v: GetPoolsPeriodEnum) => void
}

export const PoolDetails: React.FC<Props> = ({
Expand All @@ -51,14 +52,15 @@ export const PoolDetails: React.FC<Props> = ({
reloadPoolDetail,
poolStatsDetail: poolStatsDetailRD,
reloadPoolStatsDetail,
isLoading,
HistoryView,
ChartView,
disableTradingPoolAction,
disableAllPoolActions,
disablePoolActions,
walletLocked,
network
network,
poolsPeriod,
setPoolsPeriod
}) => {
const renderTitle = useMemo(() => {
const price = FP.pipe(
Expand Down Expand Up @@ -87,7 +89,6 @@ export const PoolDetails: React.FC<Props> = ({
watch={watch}
unwatch={unwatch}
price={price}
isLoading={isLoading}
isAvailablePool={isAvailablePool}
/>
)
Expand All @@ -96,7 +97,6 @@ export const PoolDetails: React.FC<Props> = ({
disableAllPoolActions,
disablePoolActions,
disableTradingPoolAction,
isLoading,
network,
poolDetailRD,
priceRatio,
Expand All @@ -122,6 +122,8 @@ export const PoolDetails: React.FC<Props> = ({
poolDetail={poolDetailRD}
priceSymbol={priceSymbol}
reloadData={reloadPoolCardsData}
poolsPeriod={poolsPeriod}
setPoolsPeriod={setPoolsPeriod}
/>
</A.Col>
<A.Col xs={24} md={16}>
Expand Down
1 change: 0 additions & 1 deletion src/renderer/components/pool/PoolTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export type Props = {
watch: FP.Lazy<void>
unwatch: FP.Lazy<void>
price: RD.RemoteData<Error, { amount: AssetAmount; symbol: string }>
isLoading?: boolean
disableTradingPoolAction: boolean
disableAllPoolActions: boolean
disablePoolActions: boolean
Expand Down
41 changes: 30 additions & 11 deletions src/renderer/components/uielements/chart/PoolDetailsChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,6 @@ const Chart: React.FC<ChartProps> = (props): JSX.Element => {
return renderChart
}

// Definition for time range buttons
const TIME_RANGE_BUTTONS: Record<ChartTimeFrame, { labelId: string; tooltipId: string }> = {
week: { labelId: 'common.time.days7.short', tooltipId: 'common.time.days7' },
month: { labelId: 'common.time.month1.short', tooltipId: 'common.time.month1' },
threeMonths: { labelId: 'common.time.months3.short', tooltipId: 'common.time.months3' },
year: { labelId: 'common.time.year1.short', tooltipId: 'common.time.year1' },
all: { labelId: 'common.time.all.short', tooltipId: 'common.time.all' }
}
type Props = {
chartDetails: ChartDetailsRD
reloadData: FP.Lazy<void>
Expand Down Expand Up @@ -132,6 +124,33 @@ export const PoolDetailsChart: React.FC<Props> = (props: Props): JSX.Element =>
[intl, reloadData]
)

// Labels/toolTips of time range buttons
const timeRangeButtons: Record<ChartTimeFrame, { label: string; tooltip: string }> = useMemo(
() => ({
week: {
label: intl.formatMessage({ id: 'common.time.days.short' }, { days: '7' }),
tooltip: intl.formatMessage({ id: 'common.time.days' }, { days: '7' })
},
month: {
label: intl.formatMessage({ id: 'common.time.month1.short' }),
tooltip: intl.formatMessage({ id: 'common.time.month1' })
},
threeMonths: {
label: intl.formatMessage({ id: 'common.time.months3.short' }),
tooltip: intl.formatMessage({ id: 'common.time.months3' })
},
year: {
label: intl.formatMessage({ id: 'common.time.year1.short' }),
tooltip: intl.formatMessage({ id: 'common.time.year1' })
},
all: {
label: intl.formatMessage({ id: 'common.time.all.short' }),
tooltip: intl.formatMessage({ id: 'common.time.all' })
}
}),
[intl]
)

return (
<Styled.ChartContainer>
<Styled.HeaderContainer>
Expand All @@ -147,13 +166,13 @@ export const PoolDetailsChart: React.FC<Props> = (props: Props): JSX.Element =>
))}
</Styled.TypeContainer>
<Styled.TimeContainer>
{Object.entries(TIME_RANGE_BUTTONS).map(([key, { labelId, tooltipId }]) => (
<Tooltip title={intl.formatMessage({ id: tooltipId })} key={key}>
{Object.entries(timeRangeButtons).map(([key, { label, tooltip }]) => (
<Tooltip title={tooltip} key={key}>
<Styled.HeaderToggle
primary={selectedTimeFrame === key}
onClick={!isLoading ? () => setTimeFrame(key as ChartTimeFrame) : undefined}
disabled={isLoading}>
{intl.formatMessage({ id: labelId })}
{label}
</Styled.HeaderToggle>
</Tooltip>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const Value = styled(Label).attrs({
weight: 'bold',
size: 'big'
})`
margin-top: 8px;
text-transform: uppercase;
overflow: hidden;
white-space: nowrap;
Expand Down
10 changes: 6 additions & 4 deletions src/renderer/components/uielements/poolStatus/PoolStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import * as Styled from './PoolStatus.styles'

export type Props = {
label: string
extraLabel?: React.ReactNode
displayValue: string
fullValue?: string
isLoading?: boolean
}

export const PoolStatus: React.FC<Props> = (props): JSX.Element => {
const { label, displayValue, fullValue, isLoading } = props
const { label, extraLabel = <></>, displayValue, fullValue, isLoading } = props
const [showTooltip, setShowTooltip] = useState(false)
const amountRef = useRef<HTMLDivElement>(null)
const containerRef = useRef<HTMLDivElement>(null)
Expand Down Expand Up @@ -45,9 +46,10 @@ export const PoolStatus: React.FC<Props> = (props): JSX.Element => {

return (
<Styled.PoolStatusWrapper ref={containerRef} {...props}>
<Styled.Title textTransform="uppercase" color="light">
{label}
</Styled.Title>
<div className="flex items-center">
<Styled.Title textTransform="uppercase">{label}</Styled.Title>
{extraLabel}
</div>
<Styled.Value loading={isLoading} ref={amountRef} className="amount">
<TooltipContainer>{displayValue}</TooltipContainer>
</Styled.Value>
Expand Down
143 changes: 143 additions & 0 deletions src/renderer/components/uielements/pools/PoolsPeriodSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React, { useMemo } from 'react'

import { Listbox } from '@headlessui/react'
import { CheckIcon, ChevronDownIcon } from '@heroicons/react/24/outline'
import * as A from 'fp-ts/lib/Array'
import * as FP from 'fp-ts/lib/function'
import * as O from 'fp-ts/lib/Option'
import { useIntl } from 'react-intl'

import { GetPoolsPeriodEnum } from '../../../types/generated/midgard'

type PeriodItem = { value: GetPoolsPeriodEnum; label: string }

const DEFAULT_ITEM: PeriodItem = { value: GetPoolsPeriodEnum._30d, label: '30 days' }

export type Props = {
selectedValue: GetPoolsPeriodEnum
onChange: (value: GetPoolsPeriodEnum) => void
className?: string
disabled?: boolean
}

export const PoolsPeriodSelector: React.FC<Props> = (props): JSX.Element => {
const { selectedValue, onChange, disabled = false, className = '' } = props

const intl = useIntl()

const defaultItem: PeriodItem = useMemo(
() => ({ value: GetPoolsPeriodEnum._30d, label: intl.formatMessage({ id: 'common.time.days' }, { days: '30' }) }),
[intl]
)

const listItems: PeriodItem[] = useMemo(
() => [
{ value: GetPoolsPeriodEnum._7d, label: intl.formatMessage({ id: 'common.time.days' }, { days: '7' }) },
defaultItem, // 30 days
{ value: GetPoolsPeriodEnum._90d, label: intl.formatMessage({ id: 'common.time.days' }, { days: '90' }) },
{ value: GetPoolsPeriodEnum._180d, label: intl.formatMessage({ id: 'common.time.days' }, { days: '180' }) },
{ value: GetPoolsPeriodEnum._365d, label: intl.formatMessage({ id: 'common.time.days' }, { days: '365' }) }
],
[defaultItem, intl]
)

const selectedItem: PeriodItem = FP.pipe(
listItems,
// get selected wallet
A.findFirst(({ value }) => value === selectedValue),
// use first if no wallet is selected
O.getOrElse(() => DEFAULT_ITEM)
)

return (
<Listbox
value={selectedItem}
disabled={disabled}
onChange={({ value }) => {
onChange(value)
}}>
<div
className={`relative ${className}`}
onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
event.preventDefault()
event.stopPropagation()
}}>
<Listbox.Button
as="div"
className={() => `text-12
group
flex cursor-pointer
items-center
bg-bg0
py-5px
pl-20px
pr-10px font-main
text-text0
transition
duration-300
ease-in-out hover:shadow-full
hover:dark:shadow-fulld
${disabled && 'opacity-70'}
whitespace-nowrap
dark:bg-bg0d
dark:text-text0d
`}>
{({ open }) => (
<>
<span className="w-full">{selectedItem.label}</span>
<ChevronDownIcon
className={`
${open && 'rotate-180'}
ease
h-20px w-20px
group-hover:rotate-180
`}
/>
</>
)}
</Listbox.Button>
<Listbox.Options
className="
absolute z-[2000]
mt-[0px]
max-h-60 w-full overflow-auto
border
border-gray0 bg-bg0 focus:outline-none
dark:border-gray0d dark:bg-bg0d
">
{FP.pipe(
listItems,
A.map((item) => {
const selected = item.value === selectedItem.value
return (
<Listbox.Option
disabled={item.value === selectedItem.value}
className={({ selected }) =>
`flex w-full
select-none
justify-center whitespace-nowrap
py-[10px] pl-20px pr-10px
${selected && 'text-gray2 dark:text-gray2d'}
${selected ? 'cursor-disabled' : 'cursor-pointer'}
text-12 font-main
text-text0
dark:text-text0d
${!selected && 'hover:bg-gray0 hover:text-gray2'}
${!selected && 'hover:dark:bg-gray0d hover:dark:text-gray2d'}
`
}
key={item.value}
value={item}>
{item.label}
<CheckIcon className={`ml-5px h-20px w-20px text-turquoise ${selected ? 'visible' : 'invisible'}`} />
</Listbox.Option>
)
})
)}
</Listbox.Options>
</div>
</Listbox>
)
}
3 changes: 3 additions & 0 deletions src/renderer/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from '@xchainjs/xchain-util'

import { Network } from '../shared/api/types'
import { GetPoolsPeriodEnum } from './types/generated/midgard'
import { PricePoolCurrencyWeights, PricePoolAssets } from './views/pools/Pools.types'

//
Expand Down Expand Up @@ -206,3 +207,5 @@ export const SUPPORTED_LEDGER_APPS: Chain[] = [
ETHChain,
CosmosChain
]

export const DEFAULT_GET_POOLS_PERIOD = GetPoolsPeriodEnum._30d
4 changes: 2 additions & 2 deletions src/renderer/i18n/de/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ const common: CommonMessages = {
'common.details': 'Details',
'common.filter': 'Filter',
'common.all': 'Alle',
'common.time.days7': '7 Tage',
'common.time.days7.short': '7D',
'common.time.days': '{days} Tage',
'common.time.days.short': '{days}d',
'common.time.month1': '1 Monat',
'common.time.month1.short': '1M',
'common.time.months3': '3 Monate',
Expand Down
Loading

0 comments on commit d2df617

Please sign in to comment.