Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pool Overview redesign #2435

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
410 changes: 301 additions & 109 deletions centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

Large diffs are not rendered by default.

66 changes: 42 additions & 24 deletions centrifuge-app/src/components/Charts/PriceChart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Select, Shelf, Stack, Text } from '@centrifuge/fabric'
import { Box, Select, Shelf, Stack, StatusChip, Text } from '@centrifuge/fabric'
import React from 'react'
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
import { useTheme } from 'styled-components'
Expand All @@ -8,13 +8,14 @@ import { CustomizedTooltip } from './Tooltip'
export type FilterOptions = 'YTD' | '30days' | '90days'

type PriceChartProps = {
data: { day: Date; price: number }[]
data: { day: Date; price: number; apy: number }[]
currency: string
filter?: FilterOptions
setFilter?: React.Dispatch<React.SetStateAction<FilterOptions>>
isPrice: boolean
}

export const PriceChart = ({ data, currency, filter, setFilter }: PriceChartProps) => {
export const PriceChart = ({ data, currency, filter, setFilter, isPrice }: PriceChartProps) => {
const theme = useTheme()
const currentPrice = data.at(-1)?.price

Expand All @@ -34,10 +35,12 @@ export const PriceChart = ({ data, currency, filter, setFilter }: PriceChartProp
</Text>
)}
{priceDifference && (
<Text variant="body3" color={priceDifference.gte(0) ? 'statusOk' : 'statusCritical'}>
{' '}
{priceDifference.gte(0) ? '+' : ''} {priceDifference.mul(100).toFixed(2)}%
</Text>
<StatusChip status={priceDifference.gte(0) ? 'ok' : 'critical'}>
<Text variant="body3" color={priceDifference.gte(0) ? 'statusOk' : 'statusCritical'}>
{' '}
{priceDifference.gte(0) ? '+' : ''} {priceDifference.mul(100).toFixed(2)}%
</Text>
</StatusChip>
)}
</Shelf>
{filter && setFilter && (
Expand All @@ -50,16 +53,17 @@ export const PriceChart = ({ data, currency, filter, setFilter }: PriceChartProp
]}
onChange={(option) => setFilter(option.target.value as FilterOptions)}
defaultValue={filter}
hideBorder
/>
</Box>
)}
</Shelf>
<ResponsiveContainer width="100%" height="100%" minHeight="200px">
<AreaChart data={data || []} margin={{ top: 18, left: -10 }}>
<defs>
<linearGradient id="colorPrice" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={'#626262'} stopOpacity={0.4} />
<stop offset="95%" stopColor={'#908f8f'} stopOpacity={0} />
<linearGradient id="colorPoolValue" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={theme.colors.textGold} stopOpacity={0.4} />
<stop offset="95%" stopColor={theme.colors.textGold} stopOpacity={0.2} />
</linearGradient>
</defs>
<XAxis
Expand All @@ -81,28 +85,42 @@ export const PriceChart = ({ data, currency, filter, setFilter }: PriceChartProp
tickLine={false}
allowDuplicatedCategory={false}
/>
<YAxis
tickCount={6}
dataKey="price"
tickLine={false}
style={{ fontSize: '10px', fill: theme.colors.textSecondary, letterSpacing: '-0.5px' }}
tickFormatter={(tick: number) => {
return tick.toFixed(6)
}}
domain={['dataMin - 0.001', 'dataMax + 0.001']}
interval={'preserveStartEnd'}
/>
{isPrice ? (
<YAxis
tickCount={6}
dataKey="price"
tickLine={false}
style={{ fontSize: '10px', fill: theme.colors.textSecondary, letterSpacing: '-0.5px' }}
tickFormatter={(tick: number) => {
return tick.toFixed(6)
}}
domain={['dataMin - 0.001', 'dataMax + 0.001']}
interval="preserveStartEnd"
/>
) : (
<YAxis
tickCount={6}
dataKey="apy"
tickLine={false}
style={{ fontSize: '10px', fill: theme.colors.textSecondary, letterSpacing: '-0.5px' }}
tickFormatter={(tick: number) => {
return tick.toFixed(6)
}}
domain={['dataMin - 0.001', 'dataMax + 0.001']}
interval="preserveStartEnd"
/>
)}
<CartesianGrid stroke={theme.colors.borderPrimary} />
<Tooltip content={<CustomizedTooltip currency={currency} precision={6} />} />
<Area
type="monotone"
dataKey="price"
dataKey={isPrice ? 'price' : 'apy'}
strokeWidth={1}
fillOpacity={1}
fill="url(#colorPrice)"
name="Price"
name={isPrice ? 'Price' : 'APY'}
activeDot={{ fill: '#908f8f' }}
stroke="#908f8f"
stroke={theme.colors.textGold}
/>
</AreaChart>
</ResponsiveContainer>
Expand Down
6 changes: 3 additions & 3 deletions centrifuge-app/src/components/Charts/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export function TooltipContainer({ children }: { children: React.ReactNode }) {
bg="backgroundPage"
p={1}
style={{
boxShadow: '1px 3px 6px rgba(0, 0, 0, .15)',
boxShadow: '1px 3px 6px 0px rgba(0, 0, 0, 0.15)',
}}
minWidth="180px"
minWidth="250px"
gap="4px"
>
{children}
Expand All @@ -44,7 +44,7 @@ export function TooltipContainer({ children }: { children: React.ReactNode }) {

export function TooltipTitle({ children }: { children: React.ReactNode }) {
return (
<Text variant="label2" fontWeight="500">
<Text color="textPrimary" variant="label2" fontWeight="500">
{children}
</Text>
)
Expand Down
7 changes: 5 additions & 2 deletions centrifuge-app/src/components/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export type DataTableProps<T = any> = {
footer?: React.ReactNode
pageSize?: number
page?: number
headerStyles?: React.CSSProperties
} & GroupedProps

export type OrderBy = 'asc' | 'desc'
Expand Down Expand Up @@ -96,6 +97,7 @@ export const DataTable = <T extends Record<string, any>>({
defaultSortOrder = 'desc',
pageSize = Infinity,
page = 1,
headerStyles,
}: DataTableProps<T>) => {
const [orderBy, setOrderBy] = React.useState<Record<string, OrderBy>>(
defaultSortKey ? { [defaultSortKey]: defaultSortOrder } : {}
Expand All @@ -122,7 +124,7 @@ export const DataTable = <T extends Record<string, any>>({
return (
<TableGrid gridTemplateColumns={templateColumns} gridAutoRows="auto" gap={0} rowGap={0}>
{showHeader && (
<HeaderRow>
<HeaderRow styles={headerStyles}>
{columns.map((col, i) => (
<HeaderCol key={i} align={col?.align}>
<Text variant="body3">
Expand Down Expand Up @@ -203,12 +205,13 @@ const Row = styled('div')`
box-shadow: ${({ theme }) => `-1px 0 0 0 ${theme.colors.borderPrimary}, 1px 0 0 0 ${theme.colors.borderPrimary}`};
`

const HeaderRow = styled(Row)<any>(
const HeaderRow = styled(Row)<{ styles?: any }>(({ styles }) =>
css({
backgroundColor: 'backgroundSecondary',
borderStyle: 'solid',
borderWidth: '1px 0',
borderColor: 'borderPrimary',
...styles,
})
)

Expand Down
1 change: 1 addition & 0 deletions centrifuge-app/src/components/InvestRedeem/InvestForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export function InvestForm({ autoFocus, investLabel = 'Invest' }: InvestFormProp
type="submit"
loading={isInvesting}
loadingMessage={loadingMessage}
variant="secondary"
disabled={
state.isPoolBusy || (state.poolCurrency?.symbol.toLowerCase().includes('lp') && hasPendingOrder)
}
Expand Down
69 changes: 24 additions & 45 deletions centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
} from '@centrifuge/fabric'
import * as React from 'react'
import { useNavigate } from 'react-router-dom'
import { useTheme } from 'styled-components'
import { ethConfig } from '../../config'
import { formatBalance } from '../../utils/formatting'
import { useAddress } from '../../utils/useAddress'
Expand Down Expand Up @@ -97,18 +96,13 @@ function InvestRedeemInput({ defaultView: defaultViewProp }: InputProps) {
if (!state.order.remainingRedeemToken.isZero()) defaultView = 'redeem'
}
const [view, setView] = React.useState<'invest' | 'redeem'>(defaultView ?? 'invest')
const theme = useTheme()

const { data: metadata } = usePoolMetadata(pool)

return (
<Stack>
<Stack gap={2}>
{renderGmp(state.poolId, state.trancheId)}
<Flex
style={{
boxShadow: `inset 0 -2px 0 ${theme.colors.borderPrimary}`,
}}
>
<Flex>
<Tabs
selectedIndex={view === 'invest' ? 0 : 1}
onChange={(index) => setView(index === 0 ? 'invest' : 'redeem')}
Expand All @@ -117,7 +111,7 @@ function InvestRedeemInput({ defaultView: defaultViewProp }: InputProps) {
<TabsItem ariaLabel="Go to redeem tab">Redeem</TabsItem>
</Tabs>
</Flex>
<Box p={2} backgroundColor="backgroundSecondary">
<Box p={2} borderWidth="1px" borderColor="borderPrimary" borderStyle="solid" borderRadius="10px">
{state.isDataLoading ? (
<Spinner />
) : state.isAllowedToInvest ? (
Expand Down Expand Up @@ -159,44 +153,27 @@ function Header() {

return (
<Stack gap={2}>
<Text variant="heading2" textAlign="center">
{state.trancheCurrency?.symbol} investment overview
</Text>
<Text variant="heading2">{state.trancheCurrency?.symbol} investment overview</Text>
{connectedType && (
<Shelf
justifyContent="space-between"
borderWidth="1px 0"
borderColor="borderPrimary"
borderStyle="solid"
py={1}
>
<Stack>
<TextWithPlaceholder variant="body3" color="textSecondary">
Position
</TextWithPlaceholder>
<TextWithPlaceholder variant="heading4" isLoading={state.isDataLoading} width={12} variance={0}>
{formatBalance(state.investmentValue, state.poolCurrency?.displayName, 2, 0)}
</TextWithPlaceholder>
</Stack>
{/*
<Stack>
<TextWithPlaceholder variant="body3" color="textSecondary">
Cost basis
<Stack>
<TextWithPlaceholder variant="body3" color="textSecondary">
Investment position
</TextWithPlaceholder>
<Shelf gap={'3px'}>
<TextWithPlaceholder
variant="heading2"
fontWeight="bold"
isLoading={state.isDataLoading}
width={12}
variance={0}
>
{formatBalance(state.investmentValue, undefined, 2, 0)}
</TextWithPlaceholder>
<TextWithPlaceholder variant="heading4" isLoading={state.isDataLoading} width={12} variance={0}>
-
<TextWithPlaceholder variant="heading2" isLoading={state.isDataLoading} width={12} variance={0}>
{state.poolCurrency?.displayName}
</TextWithPlaceholder>
</Stack>

<Stack>
<TextWithPlaceholder variant="body3" color="textSecondary">
Profit
</TextWithPlaceholder>
<TextWithPlaceholder variant="heading4" isLoading={state.isDataLoading} width={12} variance={0}>
-
</TextWithPlaceholder>
</Stack> */}
</Shelf>
</Shelf>
</Stack>
)}
</Stack>
)
Expand All @@ -210,7 +187,9 @@ function Footer() {
<>
{state.actingAddress && connectedType === 'substrate' && (
<Stack gap={2}>
<Text variant="heading4">Transaction history</Text>
<Text variant="heading6" color="textPrimary" fontWeight={600}>
Transaction history
</Text>
<Transactions onlyMostRecent narrow address={state.actingAddress} trancheId={state.trancheId} />
</Stack>
)}
Expand Down
Loading
Loading