From 466b8a4605925de49162845ac8eea7c7d8f15024 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Fri, 11 Oct 2024 09:32:07 +0200 Subject: [PATCH 01/12] Add feedback redesign --- .../src/components/Charts/SimpleBarChart.tsx | 8 ++++--- .../components/PoolOverview/KeyMetrics.tsx | 2 +- .../PoolOverview/TransactionHistory.tsx | 23 ++++++++++--------- .../src/components/Report/ReportFilter.tsx | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/centrifuge-app/src/components/Charts/SimpleBarChart.tsx b/centrifuge-app/src/components/Charts/SimpleBarChart.tsx index 9d3e71e3fc..7f6b7ecb13 100644 --- a/centrifuge-app/src/components/Charts/SimpleBarChart.tsx +++ b/centrifuge-app/src/components/Charts/SimpleBarChart.tsx @@ -11,10 +11,12 @@ import { TooltipContainer, TooltipTitle } from './Tooltip' type SimpleBarChartProps = { currency?: CurrencyMetadata data: { name: string; yAxis: number }[] + groupBy?: string } -export const SimpleBarChart = ({ currency, data }: SimpleBarChartProps) => { +export const SimpleBarChart = ({ currency, data, groupBy }: SimpleBarChartProps) => { const theme = useTheme() + const isSmallerBar = groupBy === 'daily' || false const getOneDayPerMonth = () => { const seenMonths = new Set() @@ -56,7 +58,7 @@ export const SimpleBarChart = ({ currency, data }: SimpleBarChartProps) => { type="category" dataKey="name" ticks={getOneDayPerMonth()} - tick={} + tick={(props) => } angle={45} /> { fill={theme.colors.backgroundTertiary} strokeWidth={0} fillOpacity={1} - maxBarSize={20} + barSize={isSmallerBar ? 20 : 80} /> diff --git a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index ed169d950a..3687b6c797 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -123,7 +123,7 @@ export const KeyMetrics = ({ poolId }: Props) => { metric: 'Min. investment', value: minInvestmentPerTranche?.length ? minInvestmentPerTranche.map((tranche, index) => { - return tranche && `${tranche} ${index !== minInvestmentPerTranche?.length - 1 ? '-' : ''} ` + return tranche && `$${tranche} ${index !== minInvestmentPerTranche?.length - 1 ? '-' : ''} ` }) : '-', }, diff --git a/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx b/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx index a9c22a7f9e..7b14054c97 100644 --- a/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx +++ b/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx @@ -23,6 +23,7 @@ type Row = { hash: string netFlow?: 'positive' | 'negative' | 'neutral' label: string + sublabel?: string } export const TransactionHistory = ({ @@ -106,7 +107,7 @@ export const TransactionHistoryTable = ({ if (transaction.type === 'INCREASE_DEBT') { return { - label: 'Correction of', + label: 'Correction ↑ of', amount: transaction.amount, netFlow: 'positive', } @@ -114,7 +115,7 @@ export const TransactionHistoryTable = ({ if (transaction.type === 'DECREASE_DEBT') { return { - label: 'Correction of', + label: 'Correction ↓ of', amount: transaction.amount, netFlow: 'negative', } @@ -149,9 +150,10 @@ export const TransactionHistoryTable = ({ } return { - label: 'Principal payment from', + label: 'Sale of', amount: transaction.principalAmount, netFlow, + sublabel: 'settled into', } } @@ -195,7 +197,7 @@ export const TransactionHistoryTable = ({ const tableData = transformedTransactions.slice(0, preview ? 8 : Infinity).map((transaction) => { - const { amount, netFlow, label } = getLabelAndAmount(transaction) + const { amount, netFlow, label, sublabel } = getLabelAndAmount(transaction) return { activeAssetId, netFlow, @@ -209,6 +211,7 @@ export const TransactionHistoryTable = ({ amount: amount || 0, hash: transaction.hash, label, + sublabel, } }) || [] @@ -226,22 +229,20 @@ export const TransactionHistoryTable = ({ { align: 'left', header: , - cell: ({ activeAssetId, assetId, assetName, fromAssetId, toAssetId, toAssetName, label }: Row) => { + cell: ({ activeAssetId, assetId, assetName, fromAssetId, toAssetId, toAssetName, label, sublabel }: Row) => { const base = `${basePath}/${poolId}/assets/` - return fromAssetId || toAssetId || activeAssetId ? ( + console.log(label) + return ( {label} {assetName}{' '} {toAssetName ? ( <> {' '} - to {toAssetName} + {sublabel ? sublabel : `to`}{' '} + {toAssetName} ) : null} - ) : ( - - {assetName || `Asset ${assetId?.split('-')[1]}`} - ) }, sortKey: 'transaction', diff --git a/centrifuge-app/src/components/Report/ReportFilter.tsx b/centrifuge-app/src/components/Report/ReportFilter.tsx index e4fcb9c62e..2fc1afd540 100644 --- a/centrifuge-app/src/components/Report/ReportFilter.tsx +++ b/centrifuge-app/src/components/Report/ReportFilter.tsx @@ -189,7 +189,7 @@ export function ReportFilter({ poolId }: ReportFilterProps) { {transformDataChart?.length && ( - + )} From 7858c762ee05c5f5374c7edb8bb2a8288d143de1 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Fri, 11 Oct 2024 11:34:39 +0200 Subject: [PATCH 02/12] Add hard code for tinlake --- .../src/components/PoolCard/index.tsx | 142 +++++++++++++----- centrifuge-app/src/components/PoolList.tsx | 2 +- .../components/PoolOverview/KeyMetrics.tsx | 22 ++- .../PoolOverview/TransactionHistory.tsx | 9 +- 4 files changed, 127 insertions(+), 48 deletions(-) diff --git a/centrifuge-app/src/components/PoolCard/index.tsx b/centrifuge-app/src/components/PoolCard/index.tsx index 56a33377ab..6f6cea7d1a 100644 --- a/centrifuge-app/src/components/PoolCard/index.tsx +++ b/centrifuge-app/src/components/PoolCard/index.tsx @@ -1,6 +1,7 @@ import { CurrencyBalance, Rate, Token } from '@centrifuge/centrifuge-js' import { Box, Card, Divider, Stack, Text, Thumbnail } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' +import { useMemo } from 'react' import styled from 'styled-components' import { daysBetween } from '../../utils/date' import { formatBalance, formatBalanceAbbreviated, formatPercentage } from '../../utils/formatting' @@ -24,6 +25,10 @@ export type MetaData = { } } +type TinlakeTranchesKey = 'silver' | 'blocktowerThree' | 'blocktowerFour' + +type TrancheWithCurrency = Pick + const StyledRouterTextLink = styled(RouterTextLink)` font-size: 12px; margin-top: 8px; @@ -32,7 +37,8 @@ const StyledRouterTextLink = styled(RouterTextLink)` const StyledCard = styled(Card)` width: 100%; max-width: 100%; - height: 320px; + height: 340px; + margin-right: 12px; margin-bottom: 12px; padding: 12px; @@ -50,6 +56,36 @@ const StyledCard = styled(Card)` } ` +const tinlakeTranches = { + silver: { + Junior: '15%', + Senior: '7%', + shortDescription: + 'The New Silver 2 pool funds real estate bridge loans for fix and flip projects, maturing in 12-24 months.', + InvestorType: 'Qualified Investors', + }, + blocktowerThree: { + Junior: '15%', + Senior: '4% - 15%', + shortDescription: + 'BlockTower Credit’s BT3 pool invests in investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', + InvestorType: 'Private', + }, + blocktowerFour: { + Junior: '15%', + Senior: '4%', + shortDescription: + 'BlockTower Credit’s BT4 pool invests in investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', + InvestorType: 'Private', + }, + none: { + Junior: '-', + Senior: '-', + shortDescription: '', + InvestorType: '-', + }, +} + export type PoolCardProps = { poolId?: string name?: string @@ -59,7 +95,7 @@ export type PoolCardProps = { apr?: Rate | null | undefined status?: PoolStatusKey iconUri?: string - tranches?: Pick[] + tranches?: TrancheWithCurrency[] metaData?: MetaData createdAt?: string } @@ -77,41 +113,61 @@ export function PoolCard({ createdAt, }: PoolCardProps) { const isOneTranche = tranches && tranches?.length === 1 + const isTinlakePool = + poolId === '0x53b2d22d07E069a3b132BfeaaD275b10273d381E' || + poolId === '0x90040F96aB8f291b6d43A8972806e977631aFFdE' || + poolId === '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7' + + const tinlakeObjKey = () => { + if (name?.includes('Silver')) return 'silver' + else if (name?.includes('BlockTower Series 3')) return 'blocktowerThree' + else if (name?.includes('BlockTower Series 4')) return 'blocktowerFour' + else return 'none' + } + + const getTinlakeMinInvestment = (trancheName: 'Junior' | 'Senior') => { + if (name?.includes('Silver') && trancheName === 'Senior') return '5K' + else return '-' + } + const renderText = (text: string) => ( {text} ) - const tranchesData = tranches - ?.map((tranche) => { - const words = tranche.currency.name.trim().split(' ') - const metadata = metaData?.tranches[tranche.id] ?? null - const trancheName = words[words.length - 1] - const investmentBalance = new CurrencyBalance( - metadata?.minInitialInvestment ?? 0, - tranche.currency.decimals - ).toDecimal() - - const daysSinceCreation = createdAt ? daysBetween(createdAt, new Date()) : 0 - - function calculateApy() { - if (poolId === '4139607887') return formatPercentage(5, true, {}, 1) - if (poolId === '1655476167') return formatPercentage(15, true, {}, 1) - if (daysSinceCreation > 30 && tranche.yield30DaysAnnualized) - return formatPercentage(tranche.yield30DaysAnnualized, true, {}, 1) - if (tranche.interestRatePerSec) return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1) - return '-' - } - - return { - name: trancheName, - apr: calculateApy(), - minInvestment: - metadata && metadata.minInitialInvestment ? `$${formatBalanceAbbreviated(investmentBalance, '', 0)}` : '-', - } - }) - .reverse() + const calculateApy = (tranche: TrancheWithCurrency) => { + const daysSinceCreation = createdAt ? daysBetween(createdAt, new Date()) : 0 + if (daysSinceCreation > 30 && tranche.yield30DaysAnnualized) + return formatPercentage(tranche.yield30DaysAnnualized, true, {}, 1) + if (tranche.interestRatePerSec) return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1) + return '-' + } + + const tranchesData = useMemo(() => { + return tranches + ?.map((tranche: TrancheWithCurrency) => { + const key = tinlakeObjKey() as TinlakeTranchesKey + const words = tranche.currency.name.trim().split(' ') + const metadata = metaData?.tranches[tranche.id] ?? null + const trancheName = words[words.length - 1] + const investmentBalance = new CurrencyBalance( + metadata?.minInitialInvestment ?? 0, + tranche.currency.decimals + ).toDecimal() + + return { + name: trancheName, + apr: isTinlakePool ? tinlakeTranches[key][trancheName as 'Junior' | 'Senior'] : calculateApy(tranche), + minInvestment: isTinlakePool + ? getTinlakeMinInvestment(trancheName as 'Junior' | 'Senior') + : metadata && metadata.minInitialInvestment + ? `$${formatBalanceAbbreviated(investmentBalance, '', 0)}` + : '-', + } + }) + .reverse() + }, [calculateApy, getTinlakeMinInvestment]) return ( @@ -169,20 +225,26 @@ export function PoolCard({ {tranchesData?.map((tranche) => renderText(`${tranche.minInvestment}`))} - {metaData?.pool?.issuer?.shortDescription && ( - - - {metaData?.pool?.issuer?.shortDescription} - - - )} + {metaData?.pool?.issuer?.shortDescription || + (isTinlakePool && ( + + + {isTinlakePool + ? tinlakeTranches[tinlakeObjKey()].shortDescription + : metaData?.pool?.issuer?.shortDescription} + + + ))} {assetClass && 'Asset type'} {assetClass ?? ''} - {metaData?.pool?.investorType && 'Investor Type'} - {metaData?.pool?.investorType ?? ''} + Investor Type + + {' '} + {isTinlakePool ? tinlakeTranches[tinlakeObjKey()].InvestorType : metaData?.pool?.investorType ?? '-'} + diff --git a/centrifuge-app/src/components/PoolList.tsx b/centrifuge-app/src/components/PoolList.tsx index 9ebe37ece1..ee28dc5f14 100644 --- a/centrifuge-app/src/components/PoolList.tsx +++ b/centrifuge-app/src/components/PoolList.tsx @@ -140,7 +140,6 @@ export function poolsToPoolCardProps( ): PoolCardProps[] { return pools.map((pool) => { const metaData = typeof pool.metadata === 'string' ? metaDataById[pool.id] : pool.metadata - return { poolId: pool.id, name: metaData?.pool?.name, @@ -151,6 +150,7 @@ export function poolsToPoolCardProps( iconUri: metaData?.pool?.icon?.uri ? cent.metadata.parseMetadataUrl(metaData?.pool?.icon?.uri) : undefined, tranches: pool.tranches, metaData: metaData as MetaData, + createdAt: pool.createdAt ?? '', } }) } diff --git a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index 3687b6c797..7c8efbaa2f 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -32,6 +32,17 @@ type Tranche = Pick & { } } +type TinlakeDataKey = + | '0x53b2d22d07E069a3b132BfeaaD275b10273d381E' + | '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7' + | '0x90040F96aB8f291b6d43A8972806e977631aFFdE' + +const tinlakeData = { + '0x53b2d22d07E069a3b132BfeaaD275b10273d381E': '7% - 15% target', + '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7': '4% - 15% target', + '0x90040F96aB8f291b6d43A8972806e977631aFFdE': '4% - 15% target', +} + const getTodayValue = (data: DailyTrancheStateArr | null | undefined): DailyTrancheStateArr | undefined => { if (!data) return if (!Object.keys(data).length) return @@ -95,8 +106,9 @@ export const KeyMetrics = ({ poolId }: Props) => { }, [metadata?.tranches, pool.currency.decimals]) const isBT3BT4 = - poolId.toLowerCase() === '0x90040f96ab8f291b6d43a8972806e977631affde' || - poolId.toLowerCase() === '0x55d86d51ac3bcab7ab7d2124931fba106c8b60c7' + poolId === '0x53b2d22d07E069a3b132BfeaaD275b10273d381E' || + poolId === '0x90040F96aB8f291b6d43A8972806e977631aFFdE' || + poolId === '0x55d86d51Ac3bcAB7ab7d2124931FbA106c8b60c7' const metrics = [ { @@ -109,6 +121,8 @@ export const KeyMetrics = ({ poolId }: Props) => { ? tranchesAPY.map((tranche, index) => { return tranche && `${tranche} ${index !== tranchesAPY?.length - 1 ? '-' : ''} ` }) + : tinlakeData[poolId as TinlakeDataKey] + ? tinlakeData[poolId as TinlakeDataKey] : '-', }, ...(isBT3BT4 @@ -129,7 +143,7 @@ export const KeyMetrics = ({ poolId }: Props) => { }, { metric: 'Investor type', - value: metadata?.pool?.investorType ? metadata?.pool?.investorType : '-', + value: isBT3BT4 ? 'Private' : metadata?.pool?.investorType ?? '-', }, ...(!isTinlakePool ? [ @@ -142,7 +156,7 @@ export const KeyMetrics = ({ poolId }: Props) => { { metric: 'Pool structure', - value: metadata?.pool?.poolStructure ? metadata?.pool?.poolStructure : '-', + value: isBT3BT4 ? 'Revolving' : metadata?.pool?.poolStructure ?? '-', }, ...(metadata?.pool?.rating?.ratingValue ? [ diff --git a/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx b/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx index 7b14054c97..7ac265cefb 100644 --- a/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx +++ b/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx @@ -229,12 +229,15 @@ export const TransactionHistoryTable = ({ { align: 'left', header: , - cell: ({ activeAssetId, assetId, assetName, fromAssetId, toAssetId, toAssetName, label, sublabel }: Row) => { + cell: ({ assetId, assetName, toAssetId, toAssetName, label, sublabel, fromAssetName }: Row) => { const base = `${basePath}/${poolId}/assets/` - console.log(label) + const isCashTransfer = label === 'Cash transfer from' return ( - {label} {assetName}{' '} + {label}{' '} + + {isCashTransfer ? fromAssetName : assetName} + {' '} {toAssetName ? ( <> {' '} From ebf7036934c8863682b87d80426613c63495b8f3 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Mon, 14 Oct 2024 12:35:24 +0200 Subject: [PATCH 03/12] UI changes --- .../Charts/PoolPerformanceChart.tsx | 29 ++++++----- .../src/components/Charts/PriceChart.tsx | 2 +- .../src/components/Charts/Tooltip.tsx | 6 +-- .../InvestRedeem/InvestRedeemDrawer.tsx | 11 ++-- .../src/components/IssuerSection.tsx | 51 ++++++++++++------- .../src/components/LayoutBase/styles.tsx | 1 + .../LiquidityTransactionsSection.tsx | 2 +- .../src/components/PoolCard/index.tsx | 21 ++++---- .../components/PoolOverview/KeyMetrics.tsx | 32 +++++++----- .../PoolOverview/TrancheTokenCards.tsx | 6 +-- .../PoolOverview/TransactionHistory.tsx | 4 +- .../src/components/Report/ReportFilter.tsx | 12 +++-- .../src/pages/Pool/Overview/index.tsx | 6 +-- fabric/src/components/InputUnit/index.tsx | 2 +- fabric/src/components/Select/index.tsx | 2 +- fabric/src/theme/tokens/colors.ts | 1 + fabric/src/theme/tokens/theme.ts | 2 +- 17 files changed, 107 insertions(+), 83 deletions(-) diff --git a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx index 2e3a912f90..4751fb9058 100644 --- a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx +++ b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx @@ -22,7 +22,6 @@ type ChartData = { currency?: string seniorAPY: number | null | undefined juniorAPY: number | null - isToday: boolean } type GraphDataItemWithType = { @@ -115,7 +114,7 @@ function PoolPerformanceChart() { return true }) - const [range, setRange] = React.useState<(typeof rangeFilters)[number]>({ value: 'all', label: 'All' }) + const [range, setRange] = React.useState<(typeof rangeFilters)[number]>(rangeFilters[0]) const rangeNumber = getRangeNumber(range.value, poolAge) ?? 100 // querying chain for more accurate data, since data for today from subquery is not necessarily up to date @@ -124,6 +123,16 @@ function PoolPerformanceChart() { ? formatBalance(pool?.tranches[pool.tranches.length - 1].tokenPrice || 0, undefined, 5, 5) : null + const todayJuniorApy = pool?.tranches + ?.find((pool) => pool.seniority === 0) + ?.yield30DaysAnnualized?.toPercent() + .toNumber() + + const todaySeniorApy = pool?.tranches + ?.find((pool) => pool.seniority === 1) + ?.yield30DaysAnnualized?.toPercent() + .toNumber() + const trancheTodayPrice = calculateTranchePrices(pool as Pool) const data: ChartData[] = React.useMemo( @@ -151,9 +160,8 @@ function PoolPerformanceChart() { nav: todayAssetValue, juniorTokenPrice: tranchePrices.juniorTokenPrice ?? 0, seniorTokenPrice: tranchePrices.seniorTokenPrice ?? null, - juniorAPY: formattedJuniorAPY, - seniorAPY: formattedSeniorAPY, - isToday: true, + juniorAPY: todayJuniorApy ?? 0, + seniorAPY: todaySeniorApy, } } @@ -164,20 +172,17 @@ function PoolPerformanceChart() { seniorTokenPrice: seniorTokenPrice !== 0 ? seniorTokenPrice : null, juniorAPY: formattedJuniorAPY, seniorAPY: formattedSeniorAPY, - isToday: false, } }) || [], [truncatedPoolStates, todayAssetValue, pool, range] ) - const todayData = data.find((day) => day.isToday) - const today = { nav: todayAssetValue, price: todayPrice, currency: pool.currency.symbol, - juniorAPY: todayData?.juniorAPY, - seniorAPY: todayData?.seniorAPY, + juniorAPY: todayJuniorApy, + seniorAPY: todaySeniorApy, ...trancheTodayPrice, } @@ -421,7 +426,7 @@ function CustomLegend({ navData, { color: 'textGold', - label: 'Junior token price', + label: data.seniorTokenPrice ? 'Junior token price' : 'Token price', value: formatBalance(data.juniorTokenPrice ?? 0, '', 3), type: 'singleTrancheTokenPrice', show: true, @@ -439,7 +444,7 @@ function CustomLegend({ navData, { color: 'textGold', - label: 'Junior APY', + label: data.seniorAPY ? 'Junior APY' : 'APY', value: formatPercentage(data.juniorAPY ?? 0), show: !!data.juniorAPY, }, diff --git a/centrifuge-app/src/components/Charts/PriceChart.tsx b/centrifuge-app/src/components/Charts/PriceChart.tsx index 1ccf0a62d7..be7702bcec 100644 --- a/centrifuge-app/src/components/Charts/PriceChart.tsx +++ b/centrifuge-app/src/components/Charts/PriceChart.tsx @@ -111,7 +111,7 @@ export const PriceChart = ({ data, currency, filter, setFilter, isPrice }: Price /> )} - } /> + } /> & { currency: string; precision?: number } +type CustomizedTooltipProps = TooltipProps & { currency: string; precision?: number; isRate?: boolean } -export function CustomizedTooltip({ payload, currency, precision }: CustomizedTooltipProps) { +export function CustomizedTooltip({ payload, currency, precision, isRate }: CustomizedTooltipProps) { if (payload && payload?.length > 0) { return ( @@ -15,7 +15,7 @@ export function CustomizedTooltip({ payload, currency, precision }: CustomizedTo {typeof value !== 'number' ? formatBalance(value[1] - value[0], currency, precision) - : unit === 'percent' + : unit === 'percent' || isRate ? formatPercentage(value) : formatBalance(value, currency, precision)} diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemDrawer.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemDrawer.tsx index b08a1d5110..26b98b576d 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemDrawer.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemDrawer.tsx @@ -10,6 +10,12 @@ type DailyPoolStateProps = Pick & { apy?: Perquintill | undefined } +const apy = { + '30days': 'yield30DaysAnnualized', + '90days': 'yield90DaysAnnualized', + YTD: 'yieldYTD', +} + export function InvestRedeemDrawer({ poolId, trancheId, @@ -106,11 +112,6 @@ const TokenPriceChart = React.memo(function TokenPriceChart({ const pool = usePool(poolId) const data = React.useMemo(() => { - const apy = { - '30days': 'yield30DaysAnnualized', - '90days': 'yield90DaysAnnualized', - YTD: 'yieldYTD', - } const tokenData = dailyPoolStates?.map((state) => { return { diff --git a/centrifuge-app/src/components/IssuerSection.tsx b/centrifuge-app/src/components/IssuerSection.tsx index 8ba196b26c..38787bf630 100644 --- a/centrifuge-app/src/components/IssuerSection.tsx +++ b/centrifuge-app/src/components/IssuerSection.tsx @@ -14,7 +14,7 @@ import { } from '@centrifuge/fabric' import * as React from 'react' import { useLocation } from 'react-router' -import styled from 'styled-components' +import styled, { useTheme } from 'styled-components' import { formatPercentage } from '../utils/formatting' import { ExecutiveSummaryDialog } from './Dialogs/ExecutiveSummaryDialog' import { LabelValueStack } from './LabelValueStack' @@ -46,12 +46,6 @@ const HoverBox = styled(StyledBox)` } ` -const reportLinks = [ - { label: 'Balance sheet', href: '/balance-sheet', icon: }, - { label: 'Profit & loss', href: '/profit-and-loss', icon: }, - { label: 'Cash flow statement', href: '/cash-flow-statement', icon: }, -] - const StyledRouterTextLink = styled(RouterTextLink)` color: white; text-decoration: unset; @@ -67,6 +61,21 @@ const StyledRouterTextLink = styled(RouterTextLink)` export function ReportDetails({ metadata }: IssuerSectionProps) { const pathname = useLocation().pathname const report = metadata?.pool?.reports?.[0] + const theme = useTheme() + + const reportLinks = [ + { label: 'Balance sheet', href: '/balance-sheet', icon: }, + { + label: 'Profit & loss', + href: '/profit-and-loss', + icon: , + }, + { + label: 'Cash flow statement', + href: '/cash-flow-statement', + icon: , + }, + ] return ( <> @@ -89,7 +98,7 @@ export function ReportDetails({ metadata }: IssuerSectionProps) { > {link.icon} - + {link.label} @@ -235,19 +244,23 @@ export function RatingDetails({ metadata }: IssuerSectionProps) { export const PoolAnalysis = ({ metadata, inverted }: IssuerSectionProps & { inverted?: boolean }) => { const report = metadata?.pool?.reports?.[0] + // Not sure why some pools have N/A, it should be empty but this is a fix for those pools in the meantime + const isEmpty = report?.author.name === 'N/A' return report?.author?.name || report?.author?.title ? ( - - - Pool analysis - - - - Reviewer: {report?.author?.name || 'N/A'} - - - Title: {report?.author?.title || 'N/A'} + isEmpty ? null : ( + + + Pool analysis + + + Reviewer: {report?.author?.name || 'N/A'} + + + Title: {report?.author?.title || 'N/A'} + + - + ) ) : null } diff --git a/centrifuge-app/src/components/LayoutBase/styles.tsx b/centrifuge-app/src/components/LayoutBase/styles.tsx index 0a3be4b863..678fa116b2 100644 --- a/centrifuge-app/src/components/LayoutBase/styles.tsx +++ b/centrifuge-app/src/components/LayoutBase/styles.tsx @@ -39,6 +39,7 @@ export const Inner = styled(Grid)` width: 100vw; bottom: 0; overflow-y: auto; + padding-right: 12px; @media (min-width: ${({ theme }) => theme.breakpoints['M']}) and (max-width: ${({ theme }) => theme.breakpoints['L']}) { diff --git a/centrifuge-app/src/components/LiquidityTransactionsSection.tsx b/centrifuge-app/src/components/LiquidityTransactionsSection.tsx index 3120ae8a54..b392aa5e6e 100644 --- a/centrifuge-app/src/components/LiquidityTransactionsSection.tsx +++ b/centrifuge-app/src/components/LiquidityTransactionsSection.tsx @@ -144,7 +144,7 @@ export default function LiquidityTransactionsSection({ diff --git a/centrifuge-app/src/components/PoolCard/index.tsx b/centrifuge-app/src/components/PoolCard/index.tsx index 6f6cea7d1a..0bebe0eb83 100644 --- a/centrifuge-app/src/components/PoolCard/index.tsx +++ b/centrifuge-app/src/components/PoolCard/index.tsx @@ -37,7 +37,7 @@ const StyledRouterTextLink = styled(RouterTextLink)` const StyledCard = styled(Card)` width: 100%; max-width: 100%; - height: 340px; + height: 320px; margin-right: 12px; margin-bottom: 12px; @@ -60,22 +60,19 @@ const tinlakeTranches = { silver: { Junior: '15%', Senior: '7%', - shortDescription: - 'The New Silver 2 pool funds real estate bridge loans for fix and flip projects, maturing in 12-24 months.', + shortDescription: ' Real estate bridge loans for fix and flip projects, maturing in 12-24 months.', InvestorType: 'Qualified Investors', }, blocktowerThree: { Junior: '15%', Senior: '4% - 15%', - shortDescription: - 'BlockTower Credit’s BT3 pool invests in investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', + shortDescription: ' Investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', InvestorType: 'Private', }, blocktowerFour: { Junior: '15%', Senior: '4%', - shortDescription: - 'BlockTower Credit’s BT4 pool invests in investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', + shortDescription: 'Investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', InvestorType: 'Private', }, none: { @@ -131,7 +128,7 @@ export function PoolCard({ } const renderText = (text: string) => ( - + {text} ) @@ -199,7 +196,7 @@ export function PoolCard({ padding={isOneTranche ? 0 : '8px'} display="flex" justifyContent="space-between" - width={isOneTranche ? '50%' : '100%'} + width={isOneTranche ? '60%' : '100%'} > {!isOneTranche && ( @@ -236,11 +233,11 @@ export function PoolCard({ ))} - {assetClass && 'Asset type'} - {assetClass ?? ''} + Asset type + {assetClass ?? '-'} - Investor Type + Investor type {' '} {isTinlakePool ? tinlakeTranches[tinlakeObjKey()].InvestorType : metaData?.pool?.investorType ?? '-'} diff --git a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index 7c8efbaa2f..1347675030 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -89,11 +89,13 @@ export const KeyMetrics = ({ poolId }: Props) => { const thirtyDayAPY = getTodayValue(dailyTranches) if (!thirtyDayAPY) return null - return Object.keys(thirtyDayAPY).map((key) => { - return thirtyDayAPY[key][0].yield30DaysAnnualized - ? formatPercentage(thirtyDayAPY[key][0].yield30DaysAnnualized) - : null - }) + return Object.keys(thirtyDayAPY) + .map((key) => { + return thirtyDayAPY[key][0].yield30DaysAnnualized + ? thirtyDayAPY[key][0].yield30DaysAnnualized.toPercent().toNumber() + : 0 + }) + .sort((a, b) => a - b) }, [dailyTranches]) const minInvestmentPerTranche = useMemo(() => { @@ -101,7 +103,7 @@ export const KeyMetrics = ({ poolId }: Props) => { return Object.values(metadata.tranches).map((item) => { const minInv = new CurrencyBalance(item.minInitialInvestment ?? 0, pool.currency.decimals).toDecimal() - return item.minInitialInvestment ? formatBalanceAbbreviated(minInv, '', 0) : null + return item.minInitialInvestment ? minInv : null }) }, [metadata?.tranches, pool.currency.decimals]) @@ -117,12 +119,13 @@ export const KeyMetrics = ({ poolId }: Props) => { }, { metric: '30-day APY', - value: tranchesAPY?.length + value: tinlakeData[poolId as TinlakeDataKey] + ? tinlakeData[poolId as TinlakeDataKey] + : tranchesAPY?.length ? tranchesAPY.map((tranche, index) => { - return tranche && `${tranche} ${index !== tranchesAPY?.length - 1 ? '-' : ''} ` + const formatted = formatPercentage(tranche) + return formatted && `${formatted} ${index !== tranchesAPY?.length - 1 ? '-' : ''}` }) - : tinlakeData[poolId as TinlakeDataKey] - ? tinlakeData[poolId as TinlakeDataKey] : '-', }, ...(isBT3BT4 @@ -136,9 +139,12 @@ export const KeyMetrics = ({ poolId }: Props) => { { metric: 'Min. investment', value: minInvestmentPerTranche?.length - ? minInvestmentPerTranche.map((tranche, index) => { - return tranche && `$${tranche} ${index !== minInvestmentPerTranche?.length - 1 ? '-' : ''} ` - }) + ? minInvestmentPerTranche + .sort((a, b) => Number(a) - Number(b)) + .map((tranche, index) => { + const formatted = formatBalanceAbbreviated(tranche?.toNumber() ?? 0, '', 0) + return tranche && `$${formatted} ${index !== minInvestmentPerTranche?.length - 1 ? '-' : ''} ` + }) : '-', }, { diff --git a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx index 374666961e..07e5613370 100644 --- a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx +++ b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx @@ -34,6 +34,7 @@ export const TrancheTokenCards = ({ trancheTokens, poolId }: { trancheTokens: To header: 'Token', align: 'left', formatter: (v: any) => v, + width: '40%', }, { header: 'APY', @@ -64,7 +65,7 @@ export const TrancheTokenCards = ({ trancheTokens, poolId }: { trancheTokens: To : []), { header: '', - align: 'left', + align: 'right', formatter: (_: any, row: any) => { return }, @@ -75,13 +76,12 @@ export const TrancheTokenCards = ({ trancheTokens, poolId }: { trancheTokens: To const columns = useMemo(() => { return columnConfig.map((col, index) => { return { - align: col.align, - header: col.header, cell: (row: any) => ( {col.formatter(row.value[index], row)} ), + ...col, } }) }, [columnConfig]) diff --git a/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx b/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx index 7ac265cefb..38718364ef 100644 --- a/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx +++ b/centrifuge-app/src/components/PoolOverview/TransactionHistory.tsx @@ -229,13 +229,13 @@ export const TransactionHistoryTable = ({ { align: 'left', header: , - cell: ({ assetId, assetName, toAssetId, toAssetName, label, sublabel, fromAssetName }: Row) => { + cell: ({ assetId, assetName, toAssetId, toAssetName, label, sublabel, fromAssetName, fromAssetId }: Row) => { const base = `${basePath}/${poolId}/assets/` const isCashTransfer = label === 'Cash transfer from' return ( {label}{' '} - + {isCashTransfer ? fromAssetName : assetName} {' '} {toAssetName ? ( diff --git a/centrifuge-app/src/components/Report/ReportFilter.tsx b/centrifuge-app/src/components/Report/ReportFilter.tsx index 2fc1afd540..e79356dece 100644 --- a/centrifuge-app/src/components/Report/ReportFilter.tsx +++ b/centrifuge-app/src/components/Report/ReportFilter.tsx @@ -30,7 +30,7 @@ const StyledButton = styled(Button)` margin-bottom: 0; } & > span { - border-color: ${({ selected, theme }) => (selected ? 'transparent' : theme.colors.backgroundInverted)}; + border-color: ${({ selected, theme }) => (selected ? 'transparent' : '#B7B7B7')}; } &:hover > span { border-color: ${({ selected, theme }) => (selected ? 'transparent' : theme.colors.backgroundInverted)}; @@ -38,6 +38,10 @@ const StyledButton = styled(Button)` } ` +const StyledAnchorButton = styled(AnchorButton)` + width: 80px; +` + type ReportFilterProps = { poolId: string } @@ -175,7 +179,7 @@ export function ReportFilter({ poolId }: ReportFilterProps) { ) : null} - CSV - + {transformDataChart?.length && ( - + )} diff --git a/centrifuge-app/src/pages/Pool/Overview/index.tsx b/centrifuge-app/src/pages/Pool/Overview/index.tsx index 6a7b3fb4bd..56092e20a5 100644 --- a/centrifuge-app/src/pages/Pool/Overview/index.tsx +++ b/centrifuge-app/src/pages/Pool/Overview/index.tsx @@ -151,11 +151,7 @@ export function InvestButton(props: InvestRedeemProps) { return ( <> setOpen(false)} {...props} /> - diff --git a/fabric/src/components/InputUnit/index.tsx b/fabric/src/components/InputUnit/index.tsx index 831969820d..f5f25902f4 100644 --- a/fabric/src/components/InputUnit/index.tsx +++ b/fabric/src/components/InputUnit/index.tsx @@ -24,7 +24,7 @@ export function InputUnit({ id, label, secondaryLabel, errorMessage, inputElemen return ( - + {label && ( {label} diff --git a/fabric/src/components/Select/index.tsx b/fabric/src/components/Select/index.tsx index e6e1eb8afa..9ee2fcff4a 100644 --- a/fabric/src/components/Select/index.tsx +++ b/fabric/src/components/Select/index.tsx @@ -32,7 +32,7 @@ const StyledSelect = styled.select` cursor: pointer; line-height: inherit; text-overflow: ellipsis; - font-weight: 500; + font-weight: 400; &:disabled { cursor: default; diff --git a/fabric/src/theme/tokens/colors.ts b/fabric/src/theme/tokens/colors.ts index 2a6386261b..ba4cf42d8a 100644 --- a/fabric/src/theme/tokens/colors.ts +++ b/fabric/src/theme/tokens/colors.ts @@ -2,6 +2,7 @@ export const black = '#252B34' export const gold = '#FFC012' export const grayScale = { + 10: '#cfcfcf33', 50: '#F6F6F6', 100: '#E7E7E7', 300: '#CFCFCF', diff --git a/fabric/src/theme/tokens/theme.ts b/fabric/src/theme/tokens/theme.ts index c24d2aa394..49795cfb61 100644 --- a/fabric/src/theme/tokens/theme.ts +++ b/fabric/src/theme/tokens/theme.ts @@ -31,7 +31,7 @@ const colors = { backgroundThumbnail: grayScale[500], backgroundInverted: grayScale[800], - borderPrimary: grayScale[100], + borderPrimary: grayScale[50], borderSecondary: grayScale[300], statusDefault, From 34240289eb89def150995bf20b4baf84a6277561 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Mon, 14 Oct 2024 09:20:57 +0200 Subject: [PATCH 04/12] Add logic around invest button Fix flow invest button --- .../components/InvestRedeem/InvestRedeem.tsx | 2 + .../PoolOverview/TrancheTokenCards.tsx | 17 ++++++-- .../src/pages/Pool/Overview/index.tsx | 40 ++++++++++++++++--- fabric/src/theme/tokens/theme.ts | 2 +- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx index d0c86a1b73..b266183461 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx @@ -25,6 +25,7 @@ import { usePool, usePoolMetadata } from '../../utils/usePools' import { LiquidityRewardsContainer } from '../LiquidityRewards/LiquidityRewardsContainer' import { LiquidityRewardsProvider } from '../LiquidityRewards/LiquidityRewardsProvider' import { LoadBoundary } from '../LoadBoundary' +import { PoolMetaDataPartial } from '../PoolList' import { Transactions } from '../Portfolio/Transactions' import { Spinner } from '../Spinner' import { AnchorTextLink } from '../TextLink' @@ -35,6 +36,7 @@ import { RedeemForm } from './RedeemForm' export type InvestRedeemProps = { poolId: string trancheId: string + metadata: PoolMetaDataPartial } & InputProps // @ts-ignore diff --git a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx index 07e5613370..ab6d76957b 100644 --- a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx +++ b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx @@ -7,8 +7,17 @@ import { daysBetween } from '../../utils/date' import { formatBalance, formatPercentage } from '../../utils/formatting' import { usePool } from '../../utils/usePools' import { DataTable } from '../DataTable' +import { PoolMetaDataPartial } from '../PoolList' -export const TrancheTokenCards = ({ trancheTokens, poolId }: { trancheTokens: Token[]; poolId: string }) => { +export const TrancheTokenCards = ({ + trancheTokens, + poolId, + metadata, +}: { + trancheTokens: Token[] + poolId: string + metadata: PoolMetaDataPartial +}) => { const pool = usePool(poolId) const theme = useTheme() const isTinlakePool = poolId.startsWith('0x') @@ -66,9 +75,9 @@ export const TrancheTokenCards = ({ trancheTokens, poolId }: { trancheTokens: To { header: '', align: 'right', - formatter: (_: any, row: any) => { - return - }, + formatter: (_: any, row: any) => ( + + ), }, ] }, [pool, poolId, isTinlakePool, daysSinceCreation]) diff --git a/centrifuge-app/src/pages/Pool/Overview/index.tsx b/centrifuge-app/src/pages/Pool/Overview/index.tsx index 56092e20a5..c8e93ab037 100644 --- a/centrifuge-app/src/pages/Pool/Overview/index.tsx +++ b/centrifuge-app/src/pages/Pool/Overview/index.tsx @@ -1,9 +1,11 @@ import { CurrencyBalance, Price } from '@centrifuge/centrifuge-js' +import { useWallet } from '@centrifuge/centrifuge-react' import { Box, Button, Card, Grid, TextWithPlaceholder } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' import * as React from 'react' import { useParams } from 'react-router' import styled, { useTheme } from 'styled-components' +import { InvestRedeemContext, InvestRedeemProvider } from '../../../../src/components/InvestRedeem/InvestRedeemProvider' import { InvestRedeemProps } from '../../../components/InvestRedeem/InvestRedeem' import { InvestRedeemDrawer } from '../../../components/InvestRedeem/InvestRedeemDrawer' import { IssuerDetails, ReportDetails } from '../../../components/IssuerSection' @@ -20,7 +22,6 @@ import { formatBalance } from '../../../utils/formatting' import { getPoolValueLocked } from '../../../utils/getPoolValueLocked' import { useAverageMaturity } from '../../../utils/useAverageMaturity' import { useConnectBeforeAction } from '../../../utils/useConnectBeforeAction' -import { useIsAboveBreakpoint } from '../../../utils/useIsAboveBreakpoint' import { usePool, usePoolMetadata } from '../../../utils/usePools' import { PoolDetailHeader } from '../Header' @@ -118,7 +119,7 @@ export function PoolDetailOverview() { {tokens.length > 0 && ( }> - + )} }> @@ -144,16 +145,43 @@ export function PoolDetailOverview() { } export function InvestButton(props: InvestRedeemProps) { + const { poolId, trancheId, metadata } = props const [open, setOpen] = React.useState(false) const connectAndOpen = useConnectBeforeAction(() => setOpen(true)) - const isMedium = useIsAboveBreakpoint('M') + const { connectedType, showNetworks } = useWallet() return ( <> setOpen(false)} {...props} /> - + + + {({ state }) => { + if (!state.isAllowedToInvest && connectedType !== null) { + return ( + + ) + } else if (connectedType === null) { + return ( + + ) + } else { + return ( + + ) + } + }} + + ) } diff --git a/fabric/src/theme/tokens/theme.ts b/fabric/src/theme/tokens/theme.ts index 49795cfb61..34ac9a05c4 100644 --- a/fabric/src/theme/tokens/theme.ts +++ b/fabric/src/theme/tokens/theme.ts @@ -7,7 +7,7 @@ const statusWarning = yellowScale[800] const statusCritical = '#d43f2b' const statusPromote = '#f81071' -const statusDefaultBg = grayScale[300] +const statusDefaultBg = '#CFCFCF' const statusInfoBg = blueScale[50] const statusOkBg = '#f1f7ec' const statusWarningBg = yellowScale[50] From 78425f2ca11dbe1f33d7b7f82088b51b844ea90e Mon Sep 17 00:00:00 2001 From: katty barroso Date: Mon, 14 Oct 2024 12:45:44 +0200 Subject: [PATCH 05/12] Make table scrollable but filters fixed to top --- centrifuge-app/src/components/DataTable.tsx | 21 +- .../src/components/LayoutBase/index.tsx | 3 +- .../src/components/Report/AssetList.tsx | 9 +- .../components/Report/AssetTransactions.tsx | 2 +- .../src/components/Report/DataFilter.tsx | 412 +++++++----------- .../src/components/Report/FeeTransactions.tsx | 2 +- .../src/components/Report/InvestorList.tsx | 2 +- .../Report/InvestorTransactions.tsx | 2 +- .../components/Report/OracleTransactions.tsx | 2 +- .../src/components/Report/PoolReportPage.tsx | 33 +- .../src/components/Report/ReportFilter.tsx | 2 +- .../src/components/Report/TokenPrice.tsx | 2 +- 12 files changed, 230 insertions(+), 262 deletions(-) diff --git a/centrifuge-app/src/components/DataTable.tsx b/centrifuge-app/src/components/DataTable.tsx index c852234ddd..d388b359a2 100644 --- a/centrifuge-app/src/components/DataTable.tsx +++ b/centrifuge-app/src/components/DataTable.tsx @@ -42,6 +42,7 @@ export type DataTableProps = { defaultSortKey?: string defaultSortOrder?: OrderBy hoverable?: boolean + scrollable?: boolean /** * summary row is not included in sorting */ @@ -99,6 +100,7 @@ export const DataTable = >({ pageSize = Infinity, page = 1, headerStyles, + scrollable = false, }: DataTableProps) => { const [orderBy, setOrderBy] = React.useState>( defaultSortKey ? { [defaultSortKey]: defaultSortOrder } : {} @@ -123,9 +125,9 @@ export const DataTable = >({ const templateColumns = `[start] ${columns.map((col) => col.width ?? 'minmax(min-content, 1fr)').join(' ')} [end]` return ( - + {showHeader && ( - + {columns.map((col, i) => ( @@ -200,7 +202,15 @@ export const DataTable = >({ ) } -const TableGrid = styled(Grid)`` +const TableGrid = styled(Grid)<{ scrollable?: boolean }>` + ${({ scrollable }) => + scrollable && + css({ + height: 'calc(100vh - 180px)', + overflowY: 'auto', + overflowX: 'auto', + })} +` const Row = styled('div')` display: grid; @@ -209,12 +219,15 @@ 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)<{ styles?: any }>(({ styles }) => +const HeaderRow = styled(Row)<{ styles?: any; scrollable?: boolean }>(({ styles, scrollable }) => css({ backgroundColor: 'backgroundSecondary', borderStyle: 'solid', borderWidth: '1px 0', borderColor: 'borderPrimary', + position: scrollable ? 'sticky' : 'static', + top: scrollable ? 0 : 'auto', + zIndex: scrollable ? 10 : 'auto', ...styles, }) ) diff --git a/centrifuge-app/src/components/LayoutBase/index.tsx b/centrifuge-app/src/components/LayoutBase/index.tsx index db5cd30888..cd2eca400e 100644 --- a/centrifuge-app/src/components/LayoutBase/index.tsx +++ b/centrifuge-app/src/components/LayoutBase/index.tsx @@ -55,7 +55,8 @@ export function LayoutBase(): JSX.Element { )} - + {/* The ID functions so we can deactive scrolling in certain pages, example in the data page */} + diff --git a/centrifuge-app/src/components/Report/AssetList.tsx b/centrifuge-app/src/components/Report/AssetList.tsx index 5a9f7c7497..0166310ce4 100644 --- a/centrifuge-app/src/components/Report/AssetList.tsx +++ b/centrifuge-app/src/components/Report/AssetList.tsx @@ -309,7 +309,14 @@ export function AssetList({ pool }: { pool: Pool }) { return data.length > 0 ? ( - + ) : ( diff --git a/centrifuge-app/src/components/Report/AssetTransactions.tsx b/centrifuge-app/src/components/Report/AssetTransactions.tsx index 24ac1a1597..633f5f1390 100644 --- a/centrifuge-app/src/components/Report/AssetTransactions.tsx +++ b/centrifuge-app/src/components/Report/AssetTransactions.tsx @@ -157,7 +157,7 @@ export function AssetTransactions({ pool }: { pool: Pool }) { return data.length > 0 ? ( - + ) : ( diff --git a/centrifuge-app/src/components/Report/DataFilter.tsx b/centrifuge-app/src/components/Report/DataFilter.tsx index 6ef056c6a9..8f7a2567d2 100644 --- a/centrifuge-app/src/components/Report/DataFilter.tsx +++ b/centrifuge-app/src/components/Report/DataFilter.tsx @@ -3,6 +3,7 @@ import { useGetNetworkName } from '@centrifuge/centrifuge-react' import { AnchorButton, Box, DateInput, IconDownload, SearchInput, Select, Shelf } from '@centrifuge/fabric' import * as React from 'react' import { useNavigate } from 'react-router' +import { useIsAboveBreakpoint } from '../../../src/utils/useIsAboveBreakpoint' import { usePool } from '../../../src/utils/usePools' import { nftMetadataSchema } from '../../schemas' import { useBasePath } from '../../utils/useBasePath' @@ -44,6 +45,7 @@ export function DataFilter({ poolId }: ReportFilterProps) { const navigate = useNavigate() const basePath = useBasePath() const pool = usePool(poolId) as Pool + const isMedium = useIsAboveBreakpoint('M') const { data: domains } = useActiveDomains(pool.id) const getNetworkName = useGetNetworkName() @@ -73,272 +75,196 @@ export function DataFilter({ poolId }: ReportFilterProps) { bg="backgroundSecondary" alignItems="flex-start" > - - - { - if (event.target.value) { - setGroupBy(event.target.value as GroupBy) + name="data" + label="Data" + options={reportOptions} + value={report} + onChange={(event: React.ChangeEvent) => { + const { value } = event.target + if (value) { + navigate(`${basePath}/${pool.id}/data/${value}`) } }} /> - )} - - {report === 'asset-list' && ( - - { - return { - label: token.currency.name, - value: token.id, + {['pool-balance', 'token-price'].includes(report) && ( + + { - setLoan(event.target.value) - }} - value={loan} - options={[ - { label: 'All', value: 'all' }, - ...(loans?.map((l) => ({ value: l.id, label: })) ?? []), - ]} - /> - - )} + }} + /> + + )} - {['investor-tx', 'asset-tx', 'fee-tx'].includes(report) && ( - - { - return { - label: getNetworkName(domain.chainId), - value: String(domain.chainId), - } - }), + { label: 'All', value: 'all' }, + { label: 'Ongoing', value: 'ongoing' }, + { label: 'Repaid', value: 'repaid' }, + { label: 'Overdue', value: 'overdue' }, + ]} + value={loanStatus} + onChange={(event) => setLoanStatus(event.target.value)} + /> + + )} + + {(report === 'investor-list' || report === 'investor-tx') && ( + + setLoan(event.target.value)} + value={loan} + options={[ + { label: 'All', value: 'all' }, + ...(loans?.map((l) => ({ + value: l.id, + label: , + })) ?? []), + ]} /> - - )} - - - {!['investor-list', 'asset-list'].includes(report) && ( - <> + )} + + {['investor-tx', 'asset-tx', 'fee-tx'].includes(report) && ( - setStartDate(e.target.value)} /> + ({ + label: getNetworkName(domain.chainId), + value: String(domain.chainId), + })), + ]} + value={network} + onChange={(e) => { + const { value } = e.target + if (value) { + setNetwork(isNaN(Number(value)) ? value : Number(value)) + } + }} + /> + + + )} + + + + + setStartDate(e.target.value)} /> + + setEndDate(e.target.value)} /> + + } + small + variant="inverted" + style={{ marginLeft: '12px', marginTop: '22px' }} + > + CSV + + + + {['investor-tx', 'investor-list'].includes(report) && ( + + setAddress(e.target.value)} + /> + + )} ) } diff --git a/centrifuge-app/src/components/Report/FeeTransactions.tsx b/centrifuge-app/src/components/Report/FeeTransactions.tsx index d4db8adf75..34a72162a5 100644 --- a/centrifuge-app/src/components/Report/FeeTransactions.tsx +++ b/centrifuge-app/src/components/Report/FeeTransactions.tsx @@ -124,7 +124,7 @@ export function FeeTransactions({ pool }: { pool: Pool }) { return data.length > 0 ? ( - + ) : ( diff --git a/centrifuge-app/src/components/Report/InvestorList.tsx b/centrifuge-app/src/components/Report/InvestorList.tsx index 792c32eb70..2d5e4cda5c 100644 --- a/centrifuge-app/src/components/Report/InvestorList.tsx +++ b/centrifuge-app/src/components/Report/InvestorList.tsx @@ -170,7 +170,7 @@ export function InvestorList({ pool }: { pool: Pool }) { return data.length > 0 ? ( - + ) : ( diff --git a/centrifuge-app/src/components/Report/InvestorTransactions.tsx b/centrifuge-app/src/components/Report/InvestorTransactions.tsx index 7754d6bd24..95dea6d84a 100644 --- a/centrifuge-app/src/components/Report/InvestorTransactions.tsx +++ b/centrifuge-app/src/components/Report/InvestorTransactions.tsx @@ -266,7 +266,7 @@ export function InvestorTransactions({ pool }: { pool: Pool }) { return data.length > 0 ? ( - + ) : ( diff --git a/centrifuge-app/src/components/Report/OracleTransactions.tsx b/centrifuge-app/src/components/Report/OracleTransactions.tsx index c36ac98451..507ae03b38 100644 --- a/centrifuge-app/src/components/Report/OracleTransactions.tsx +++ b/centrifuge-app/src/components/Report/OracleTransactions.tsx @@ -96,7 +96,7 @@ export function OracleTransactions({ pool }: { pool: Pool }) { return data.length > 0 ? ( - + ) : ( diff --git a/centrifuge-app/src/components/Report/PoolReportPage.tsx b/centrifuge-app/src/components/Report/PoolReportPage.tsx index c2f0124750..20db9daf21 100644 --- a/centrifuge-app/src/components/Report/PoolReportPage.tsx +++ b/centrifuge-app/src/components/Report/PoolReportPage.tsx @@ -12,6 +12,7 @@ import { ReportFilter } from './ReportFilter' export function PoolReportPage({ header }: { header: React.ReactNode }) { const params = useParams<{ pid: string; '*': string }>() const location = useLocation() + const isReportingTab = location.pathname.includes('reporting') const { pid: poolId } = params if (!poolId) throw new Error('Pool not found') @@ -20,24 +21,44 @@ export function PoolReportPage({ header }: { header: React.ReactNode }) { {header} - {location.pathname.includes('reporting') ? : } + {isReportingTab ? : } - + ) } -function PoolDetailReporting({ poolId }: { poolId: string }) { +function PoolDetailReporting({ poolId, isReportingTab }: { poolId: string; isReportingTab: boolean }) { const pool = usePool(poolId) as Pool + const contentWrapperRef = React.useRef(null) + if (!poolId || !pool) { return } + // We want to scroll within the table and not the page, + // this way we can keep the filters on top of the page while scrolling on the table + React.useEffect(() => { + const contentWrapper = document.getElementById('content-wrapper') + + if (contentWrapper && !isReportingTab) { + contentWrapper.style.overflow = 'hidden' + } + + return () => { + if (contentWrapper) { + contentWrapper.style.overflow = '' + } + } + }, [isReportingTab]) + return ( - }> - - +
+ }> + + +
) } diff --git a/centrifuge-app/src/components/Report/ReportFilter.tsx b/centrifuge-app/src/components/Report/ReportFilter.tsx index e79356dece..a764735942 100644 --- a/centrifuge-app/src/components/Report/ReportFilter.tsx +++ b/centrifuge-app/src/components/Report/ReportFilter.tsx @@ -30,7 +30,7 @@ const StyledButton = styled(Button)` margin-bottom: 0; } & > span { - border-color: ${({ selected, theme }) => (selected ? 'transparent' : '#B7B7B7')}; + border-color: ${({ selected }) => (selected ? 'transparent' : '#B7B7B7')}; } &:hover > span { border-color: ${({ selected, theme }) => (selected ? 'transparent' : theme.colors.backgroundInverted)}; diff --git a/centrifuge-app/src/components/Report/TokenPrice.tsx b/centrifuge-app/src/components/Report/TokenPrice.tsx index d461862ba1..7e1f2a992d 100644 --- a/centrifuge-app/src/components/Report/TokenPrice.tsx +++ b/centrifuge-app/src/components/Report/TokenPrice.tsx @@ -294,7 +294,7 @@ export function TokenPrice({ pool }: { pool: Pool }) { return poolStates?.length > 0 ? ( - + ) : ( From 1f640eea1b0339bbb10066b17c7785e8ac532610 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Mon, 14 Oct 2024 14:26:11 +0200 Subject: [PATCH 06/12] UI fixes --- .../Charts/PoolPerformanceChart.tsx | 18 +++++++----- centrifuge-app/src/components/DataTable.tsx | 8 ++++- .../src/components/IssuerSection.tsx | 23 +++++++++------ .../components/LayoutBase/LayoutSection.tsx | 2 +- .../src/components/LayoutBase/styles.tsx | 2 +- centrifuge-app/src/components/PillButton.tsx | 8 +++-- .../src/components/PoolCard/index.tsx | 29 +++++++++++++++---- centrifuge-app/src/components/PoolList.tsx | 17 +++++++++-- .../PoolOverview/TrancheTokenCards.tsx | 2 +- .../src/components/Report/DataFilter.tsx | 4 +-- .../src/components/Report/ReportFilter.tsx | 3 +- centrifuge-app/src/components/Tooltips.tsx | 5 ++-- .../src/pages/Pool/Overview/index.tsx | 12 ++++++-- fabric/src/components/Button/VisualButton.tsx | 4 +-- fabric/src/components/Button/WalletButton.tsx | 6 ++-- fabric/src/components/Select/index.tsx | 10 +++++-- fabric/src/components/Tabs/index.tsx | 21 +++++++++++--- fabric/src/icon-svg/icon-download.svg | 7 +++-- fabric/src/theme/tokens/theme.ts | 14 ++++----- 19 files changed, 135 insertions(+), 60 deletions(-) diff --git a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx index 4751fb9058..2c6474a33a 100644 --- a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx +++ b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx @@ -222,10 +222,10 @@ function PoolPerformanceChart() { Pool performance
setSelectedTabIndex(index)}> - + Price - + APY @@ -263,7 +263,7 @@ function PoolPerformanceChart() { formatBalanceAbbreviated(tick, '', 0)} yAxisId="left" width={80} @@ -271,7 +271,7 @@ function PoolPerformanceChart() { formatBalanceAbbreviated(tick, '', 2)} yAxisId="right" orientation="right" @@ -475,13 +475,15 @@ function CustomLegend({ } return ( - + {hasType(item) ? ( - - ) : ( + + + ) : ( + {item.label} )} @@ -512,7 +514,7 @@ export const CustomTick = ({ x, y, payload }: CustomTickProps) => { return ( ` ${({ scrollable }) => scrollable && css({ - height: 'calc(100vh - 180px)', + maxHeight: 'calc(100vh - 180px)', overflowY: 'auto', overflowX: 'auto', })} @@ -228,6 +228,8 @@ const HeaderRow = styled(Row)<{ styles?: any; scrollable?: boolean }>(({ styles, position: scrollable ? 'sticky' : 'static', top: scrollable ? 0 : 'auto', zIndex: scrollable ? 10 : 'auto', + borderTopLeftRadius: '8px', + borderTopRightRadius: '8px', ...styles, }) ) @@ -255,6 +257,10 @@ export const DataRow = styled(Row)` '&:focus-visible': { boxShadow: 'inset 0 0 0 3px var(--fabric-focus)', }, + '&:last-child': { + borderBottomLeftRadius: '8px', + borderBottomRightRadius: '8px', + }, })} ` diff --git a/centrifuge-app/src/components/IssuerSection.tsx b/centrifuge-app/src/components/IssuerSection.tsx index 38787bf630..be76a0e044 100644 --- a/centrifuge-app/src/components/IssuerSection.tsx +++ b/centrifuge-app/src/components/IssuerSection.tsx @@ -28,7 +28,7 @@ type IssuerSectionProps = { } const StyledBox = styled(Box)` - padding: 30px 20px; + padding: 24px; &:hover { background: ${SUBTLE_GRAY}; border-radius: 0px; @@ -37,12 +37,12 @@ const StyledBox = styled(Box)` const HoverBox = styled(StyledBox)` padding: 8px 22px; - border-radius: 4px; background-color: ${SUBTLE_GRAY}; + border: 3px solid transparent; + border-radius: 4px; &:hover { - a { - color: ${({ theme }) => theme.colors.textGold}; - } + border-radius: 4px; + border-color: #91969b1a; } ` @@ -151,8 +151,8 @@ export function IssuerDetails({ metadata }: IssuerSectionProps) { {metadata?.pool?.issuer.logo && ( @@ -199,14 +199,19 @@ const Links = ({ links }: { links: { label: string; href?: string; show: boolean if (link.onClick) { return ( - + {link.label} ) } return ( - + {link.label} ) diff --git a/centrifuge-app/src/components/LayoutBase/LayoutSection.tsx b/centrifuge-app/src/components/LayoutBase/LayoutSection.tsx index 2cdb7f2ccb..8c97517b0c 100644 --- a/centrifuge-app/src/components/LayoutBase/LayoutSection.tsx +++ b/centrifuge-app/src/components/LayoutBase/LayoutSection.tsx @@ -12,7 +12,7 @@ type Props = { export function LayoutSection({ title, titleAddition, subtitle, headerRight, children, ...boxProps }: Props) { return ( - + {(title || titleAddition || subtitle || headerRight) && ( diff --git a/centrifuge-app/src/components/LayoutBase/styles.tsx b/centrifuge-app/src/components/LayoutBase/styles.tsx index 678fa116b2..b69340663e 100644 --- a/centrifuge-app/src/components/LayoutBase/styles.tsx +++ b/centrifuge-app/src/components/LayoutBase/styles.tsx @@ -147,7 +147,7 @@ export const WalletInner = styled(Stack)` @media (min-width: ${({ theme }) => theme.breakpoints[BREAK_POINT_COLUMNS]}) { justify-content: flex-end; height: 50px; - margin-right: 40px; + margin-right: 30px; } ` diff --git a/centrifuge-app/src/components/PillButton.tsx b/centrifuge-app/src/components/PillButton.tsx index cea7e31c8e..84731bacd9 100644 --- a/centrifuge-app/src/components/PillButton.tsx +++ b/centrifuge-app/src/components/PillButton.tsx @@ -14,11 +14,13 @@ const Pill = styled.button<{ variant?: 'small' | 'regular' }>( backgroundColor: 'backgroundSecondary', textDecoration: 'none', borderRadius: 20, + lineHeight: 20, '&:visited, &:active': { color: 'textPrimary', }, '&:hover': { - color: 'textGold', + color: 'textInverted', + backgroundColor: 'textPrimary', }, }), ({ theme }) => ({ @@ -32,11 +34,11 @@ const Pill = styled.button<{ variant?: 'small' | 'regular' }>( ? css({ borderRadius: '20px', fontSize: '14px', - padding: '2px 8px', + padding: '8px 16px', }) : css({ borderRadius: '12px', - padding: '2px 10px', + padding: '4px 12px', fontSize: '12px', }) ) diff --git a/centrifuge-app/src/components/PoolCard/index.tsx b/centrifuge-app/src/components/PoolCard/index.tsx index 0bebe0eb83..8ed5b70083 100644 --- a/centrifuge-app/src/components/PoolCard/index.tsx +++ b/centrifuge-app/src/components/PoolCard/index.tsx @@ -2,7 +2,7 @@ import { CurrencyBalance, Rate, Token } from '@centrifuge/centrifuge-js' import { Box, Card, Divider, Stack, Text, Thumbnail } from '@centrifuge/fabric' import Decimal from 'decimal.js-light' import { useMemo } from 'react' -import styled from 'styled-components' +import styled, { useTheme } from 'styled-components' import { daysBetween } from '../../utils/date' import { formatBalance, formatBalanceAbbreviated, formatPercentage } from '../../utils/formatting' import { CardHeader } from '../ListItemCardStyles' @@ -44,7 +44,8 @@ const StyledCard = styled(Card)` padding: 12px; &:hover { - border: 1px solid ${({ theme }) => theme.colors.backgroundInverted}; + border: 1px solid ${({ theme }) => theme.colors.backgroundTertiary}; + box-shadow: 0px 20px 24px -4px rgba(16, 24, 40, 0.08), 0px 8px 8px -4px rgba(16, 24, 40, 0.03); } @media (min-width: ${({ theme }) => theme.breakpoints['M']}) { @@ -65,7 +66,7 @@ const tinlakeTranches = { }, blocktowerThree: { Junior: '15%', - Senior: '4% - 15%', + Senior: '4%', shortDescription: ' Investment-grade consumer ABS, auto ABS, and CLOs under 4 years.', InvestorType: 'Private', }, @@ -109,6 +110,7 @@ export function PoolCard({ metaData, createdAt, }: PoolCardProps) { + const theme = useTheme() const isOneTranche = tranches && tranches?.length === 1 const isTinlakePool = poolId === '0x53b2d22d07E069a3b132BfeaaD275b10273d381E' || @@ -137,7 +139,9 @@ export function PoolCard({ const daysSinceCreation = createdAt ? daysBetween(createdAt, new Date()) : 0 if (daysSinceCreation > 30 && tranche.yield30DaysAnnualized) return formatPercentage(tranche.yield30DaysAnnualized, true, {}, 1) - if (tranche.interestRatePerSec) return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1) + if (tranche.interestRatePerSec) { + return formatPercentage(tranche.interestRatePerSec.toAprPercent(), true, {}, 1) + } return '-' } @@ -153,9 +157,14 @@ export function PoolCard({ tranche.currency.decimals ).toDecimal() + const apy = () => { + if (calculateApy(tranche) === '0.0%') return '-' + else return calculateApy(tranche) + } + return { name: trancheName, - apr: isTinlakePool ? tinlakeTranches[key][trancheName as 'Junior' | 'Senior'] : calculateApy(tranche), + apr: isTinlakePool ? tinlakeTranches[key][trancheName as 'Junior' | 'Senior'] : apy(), minInvestment: isTinlakePool ? getTinlakeMinInvestment(trancheName as 'Junior' | 'Senior') : metadata && metadata.minInitialInvestment @@ -177,7 +186,15 @@ export function PoolCard({ {iconUri ? ( - + ) : ( )} diff --git a/centrifuge-app/src/components/PoolList.tsx b/centrifuge-app/src/components/PoolList.tsx index ee28dc5f14..2d4c3b9a74 100644 --- a/centrifuge-app/src/components/PoolList.tsx +++ b/centrifuge-app/src/components/PoolList.tsx @@ -22,6 +22,19 @@ const PoolCardBox = styled(Box)` } ` +const StyledBox = styled(Box)` + background-color: transparent; + border: none; + &:hover { + svg { + color: ${({ theme }) => theme.colors.textGold}; + } + div { + color: ${({ theme }) => theme.colors.textGold}; + } + } +` + const upcomingPools: PoolCardProps[] = [] export function PoolList() { @@ -93,7 +106,7 @@ export function PoolList() { {!metadataIsLoading && archivedPools.length > 0 && ( <> - + {!showArchived && } - + {showArchived && } )} diff --git a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx index ab6d76957b..1bedfd6d58 100644 --- a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx +++ b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx @@ -58,7 +58,7 @@ export const TrancheTokenCards = ({ { header: 'Token price', align: 'left', - formatter: (v: any) => (v ? formatBalance(v, pool?.currency.symbol, pool?.currency.decimals) : '-'), + formatter: (v: any) => (v ? formatBalance(v, pool?.currency.symbol, 6) : '-'), }, ...(pool.tranches.length > 1 ? [ diff --git a/centrifuge-app/src/components/Report/DataFilter.tsx b/centrifuge-app/src/components/Report/DataFilter.tsx index 8f7a2567d2..6b146626b0 100644 --- a/centrifuge-app/src/components/Report/DataFilter.tsx +++ b/centrifuge-app/src/components/Report/DataFilter.tsx @@ -245,12 +245,12 @@ export function DataFilter({ poolId }: ReportFilterProps) { disabled={!csvData} download={csvData?.fileName} href={csvData?.dataUrl} - icon={} + icon={} small variant="inverted" style={{ marginLeft: '12px', marginTop: '22px' }} > - CSV + Download diff --git a/centrifuge-app/src/components/Report/ReportFilter.tsx b/centrifuge-app/src/components/Report/ReportFilter.tsx index a764735942..46708126ef 100644 --- a/centrifuge-app/src/components/Report/ReportFilter.tsx +++ b/centrifuge-app/src/components/Report/ReportFilter.tsx @@ -30,6 +30,7 @@ const StyledButton = styled(Button)` margin-bottom: 0; } & > span { + border-width: 1px; border-color: ${({ selected }) => (selected ? 'transparent' : '#B7B7B7')}; } &:hover > span { @@ -187,7 +188,7 @@ export function ReportFilter({ poolId }: ReportFilterProps) { small variant="inverted" > - CSV + Download diff --git a/centrifuge-app/src/components/Tooltips.tsx b/centrifuge-app/src/components/Tooltips.tsx index f97ce41d58..411ab874ec 100644 --- a/centrifuge-app/src/components/Tooltips.tsx +++ b/centrifuge-app/src/components/Tooltips.tsx @@ -349,9 +349,10 @@ export type TooltipsProps = { label?: string | React.ReactNode props?: any size?: 'med' | 'sm' + color?: string } & Partial> -export function Tooltips({ type, label: labelOverride, size = 'sm', props, ...textProps }: TooltipsProps) { +export function Tooltips({ type, label: labelOverride, size = 'sm', props, color, ...textProps }: TooltipsProps) { const { label, body } = type ? tooltipText[type] : { label: labelOverride, body: textProps.body } return ( @@ -359,7 +360,7 @@ export function Tooltips({ type, label: labelOverride, size = 'sm', props, ...te {labelOverride || label} diff --git a/centrifuge-app/src/pages/Pool/Overview/index.tsx b/centrifuge-app/src/pages/Pool/Overview/index.tsx index c8e93ab037..c0483d37bb 100644 --- a/centrifuge-app/src/pages/Pool/Overview/index.tsx +++ b/centrifuge-app/src/pages/Pool/Overview/index.tsx @@ -123,12 +123,18 @@ export function PoolDetailOverview() {
)} }> - - + + {metadata?.pool?.reports?.length || !isTinlakePool ? ( - + ) : null} diff --git a/fabric/src/components/Button/VisualButton.tsx b/fabric/src/components/Button/VisualButton.tsx index f16acb62ee..65b9f03f99 100644 --- a/fabric/src/components/Button/VisualButton.tsx +++ b/fabric/src/components/Button/VisualButton.tsx @@ -93,7 +93,7 @@ export const StyledButton = styled.span( color: $disabled ? fgDisabled : $active ? fgHover : fg, backgroundColor: $disabled ? bgDisabled : $active ? bgHover : bg, borderColor: $disabled ? borderDisabled : $active ? borderHover : border, - borderWidth: 1, + borderWidth: 3, borderRadius: 'button', pointerEvents: $disabled ? 'none' : 'initial', minHeight: $small ? 32 : 40, @@ -171,7 +171,7 @@ export function VisualButton({ ) : ( <> {children && ( - + {children} )} diff --git a/fabric/src/components/Button/WalletButton.tsx b/fabric/src/components/Button/WalletButton.tsx index 47a32bd635..0488669e84 100644 --- a/fabric/src/components/Button/WalletButton.tsx +++ b/fabric/src/components/Button/WalletButton.tsx @@ -24,16 +24,18 @@ const StyledButton = styled.button` display: inline-block; width: 100%; padding: 0; - border: none; + border-width: 3; + border-color: transparent; appearance: none; background-color: ${({ theme }) => theme.colors.backgroundPrimary}; outline: 0; border-radius: 40px; white-space: nowrap; & > span { + border-width: 3; border-color: ${({ theme }) => theme.colors.backgroundPrimary}; :hover { - border-color: ${({ theme }) => theme.colors.backgroundPrimary}; + border: ${({ theme }) => `3px solid ${theme.colors.borderSecondary}`}; } } ` diff --git a/fabric/src/components/Select/index.tsx b/fabric/src/components/Select/index.tsx index 9ee2fcff4a..c3e3088bcc 100644 --- a/fabric/src/components/Select/index.tsx +++ b/fabric/src/components/Select/index.tsx @@ -44,6 +44,7 @@ export function SelectInner({ placeholder, disabled, small, + hideBorder, ...rest }: Omit) { return ( @@ -68,7 +69,12 @@ export function SelectInner({ )} {options.map((option, index) => ( - ))} @@ -88,7 +94,7 @@ export function Select({ label, errorMessage, id, hideBorder, ...rest }: SelectP errorMessage={errorMessage} inputElement={ - + } /> diff --git a/fabric/src/components/Tabs/index.tsx b/fabric/src/components/Tabs/index.tsx index 1d5ff62d13..25ffc82ddf 100644 --- a/fabric/src/components/Tabs/index.tsx +++ b/fabric/src/components/Tabs/index.tsx @@ -9,6 +9,7 @@ export type TabsProps = { selectedIndex: number onChange?: (index: number) => void children: (React.ReactElement | string | boolean | null | undefined)[] + variant?: 'primary' | 'secondary' } export function Tabs({ selectedIndex, onChange, children }: TabsProps) { @@ -29,7 +30,12 @@ export function Tabs({ selectedIndex, onChange, children }: TabsProps) { ) } -const StyledTabsItem = styled.button<{ $active?: boolean; styleOverrides?: React.CSSProperties, showBorder?: boolean }>( +const StyledTabsItem = styled.button<{ + $active?: boolean + styleOverrides?: React.CSSProperties + showBorder?: boolean + variant: 'primary' | 'secondary' +}>( { display: 'flex', alignItems: 'center', @@ -43,18 +49,23 @@ const StyledTabsItem = styled.button<{ $active?: boolean; styleOverrides?: React appearance: 'none', background: 'transparent', }, - ({ $active, theme, styleOverrides, showBorder }) => { + ({ $active, theme, styleOverrides, showBorder, variant }) => { + console.log(variant) return css({ paddingTop: 1, paddingLeft: 2, paddingRight: 2, paddingBottom: 2, color: $active ? 'textPrimary' : 'textSecondary', - boxShadow: $active ? `inset 0 -2px 0 ${theme.colors.textGold}` : showBorder ? `inset 0 -2px 0 ${theme.colors.textDisabled}` : 'none', + boxShadow: $active + ? `inset 0 -2px 0 ${variant === 'secondary' ? theme.colors.textPrimary : theme.colors.textGold}` + : showBorder + ? `inset 0 -2px 0 ${theme.colors.textDisabled}` + : 'none', fontWeight: 400, '&:hover, &:active, &:focus-visible': { - color: 'textGold', + color: $active ? 'textPrimary' : 'textGold', }, ...styleOverrides, }) @@ -80,6 +91,7 @@ export function TabsItem({ ariaLabel, styleOverrides, showBorder, + variant = 'primary', ...rest }: TabsItemPrivateProps) { return ( @@ -90,6 +102,7 @@ export function TabsItem({ aria-label={ariaLabel} styleOverrides={styleOverrides} showBorder={showBorder} + variant={variant} {...rest} > diff --git a/fabric/src/icon-svg/icon-download.svg b/fabric/src/icon-svg/icon-download.svg index 36e3604eb9..b1b7145f29 100644 --- a/fabric/src/icon-svg/icon-download.svg +++ b/fabric/src/icon-svg/icon-download.svg @@ -1,4 +1,5 @@ - - - + + + + diff --git a/fabric/src/theme/tokens/theme.ts b/fabric/src/theme/tokens/theme.ts index 34ac9a05c4..ed707ad8a9 100644 --- a/fabric/src/theme/tokens/theme.ts +++ b/fabric/src/theme/tokens/theme.ts @@ -7,7 +7,7 @@ const statusWarning = yellowScale[800] const statusCritical = '#d43f2b' const statusPromote = '#f81071' -const statusDefaultBg = '#CFCFCF' +const statusDefaultBg = grayScale[100] const statusInfoBg = blueScale[50] const statusOkBg = '#f1f7ec' const statusWarningBg = yellowScale[50] @@ -58,9 +58,9 @@ const colors = { textButtonPrimaryPressed: black, textButtonPrimaryDisabled: grayScale[500], borderButtonPrimary: gold, - borderButtonPrimaryFocus: yellowScale[800], - borderButtonPrimaryHover: yellowScale[800], - borderButtonPrimaryPressed: yellowScale[800], + borderButtonPrimaryFocus: yellowScale[100], + borderButtonPrimaryHover: yellowScale[100], + borderButtonPrimaryPressed: yellowScale[100], borderButtonPrimaryDisabled: 'transparent', shadowButtonPrimary: 'transparent', @@ -108,9 +108,9 @@ const colors = { textButtonInvertedPressed: black, textButtonInvertedDisabled: grayScale[500], borderButtonInverted: grayScale[100], - borderButtonInvertedFocus: black, - borderButtonInvertedHover: black, - borderButtonInvertedPressed: black, + borderButtonInvertedFocus: grayScale[50], + borderButtonInvertedHover: grayScale[50], + borderButtonInvertedPressed: grayScale[50], borderButtonInvertedDisabled: 'transparent', shadowButtonInverted: 'transparent', } From d1b0e734928294fc83274a0de104854f0e96c733 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Tue, 15 Oct 2024 09:31:40 +0200 Subject: [PATCH 07/12] Add nav bar style changes --- .../src/components/Charts/PoolPerformanceChart.tsx | 2 +- centrifuge-app/src/components/LayoutBase/styles.tsx | 8 +++++--- centrifuge-app/src/components/Menu/PageLink.tsx | 5 +++-- centrifuge-app/src/components/Menu/Toggle.tsx | 5 ++++- centrifuge-app/src/components/PoolCard/index.tsx | 2 +- .../src/components/PoolOverview/TrancheTokenCards.tsx | 2 +- centrifuge-app/src/components/Report/PoolReportPage.tsx | 8 ++++---- 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx index 2c6474a33a..2f3c45d9d5 100644 --- a/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx +++ b/centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx @@ -174,7 +174,7 @@ function PoolPerformanceChart() { seniorAPY: formattedSeniorAPY, } }) || [], - [truncatedPoolStates, todayAssetValue, pool, range] + [truncatedPoolStates, todayAssetValue, pool, range, todayJuniorApy, todaySeniorApy] ) const today = { diff --git a/centrifuge-app/src/components/LayoutBase/styles.tsx b/centrifuge-app/src/components/LayoutBase/styles.tsx index b69340663e..f838be30a6 100644 --- a/centrifuge-app/src/components/LayoutBase/styles.tsx +++ b/centrifuge-app/src/components/LayoutBase/styles.tsx @@ -52,7 +52,8 @@ export const Inner = styled(Grid)` @media (min-width: ${({ theme }) => theme.breakpoints['L']}) { width: 15vw; background-color: ${({ theme }) => theme.colors.backgroundInverted}; - padding-left: 16px; + padding-left: 12px; + padding-right: 20px; height: 100vh; } ` @@ -100,7 +101,7 @@ export const LogoContainer = styled(Stack)` height: ${HEADER_HEIGHT}px; justify-content: center; - padding-left: 12px; + padding-left: 8px; @media (min-width: ${({ theme }) => theme.breakpoints['M']}) and (max-width: ${({ theme }) => theme.breakpoints['L']}) { @@ -111,7 +112,7 @@ export const LogoContainer = styled(Stack)` @media (min-width: ${({ theme }) => theme.breakpoints['L']}) { justify-content: start; - padding-top: ${({ theme }) => theme.space[2]}px; + padding-top: ${({ theme }) => theme.space[3]}px; } ` @@ -166,6 +167,7 @@ export const FooterContainer = styled(Box)` position: sticky; bottom: 0; width: 100%; + padding-left: 4px; @media (min-width: ${({ theme }) => theme.breakpoints[BREAK_POINT_COLUMNS]}) { position: sticky; diff --git a/centrifuge-app/src/components/Menu/PageLink.tsx b/centrifuge-app/src/components/Menu/PageLink.tsx index 005f06f349..20e37873bd 100644 --- a/centrifuge-app/src/components/Menu/PageLink.tsx +++ b/centrifuge-app/src/components/Menu/PageLink.tsx @@ -9,13 +9,14 @@ const Root = styled(Text)<{ isActive?: boolean; stacked?: boolean }>` ${baseButton} ${primaryButton} grid-template-columns: ${({ stacked, theme }) => (stacked ? '1fr' : `${theme.sizes.iconSmall}px 1fr`)}; - color: ${({ isActive, theme }) => - isActive ? theme.colors.textGold : theme.colors.textInverted}; /* Example styling */ + color: ${({ isActive, theme }) => (isActive ? theme.colors.textGold : theme.colors.textInverted)}; font-size: 14px; font-weight: 500; background-color: transparent; + border-radius: 4px; &:hover { color: ${({ theme }) => theme.colors.textGold}; + background-color: rgba(145, 150, 155, 0.13); } ` diff --git a/centrifuge-app/src/components/Menu/Toggle.tsx b/centrifuge-app/src/components/Menu/Toggle.tsx index 934584b765..894ab01c63 100644 --- a/centrifuge-app/src/components/Menu/Toggle.tsx +++ b/centrifuge-app/src/components/Menu/Toggle.tsx @@ -9,8 +9,11 @@ export const Toggle = styled(Text)<{ isActive?: boolean; stacked?: boolean }>` grid-template-columns: ${({ stacked, theme }) => stacked ? '1fr' : `${theme.sizes.iconSmall}px 1fr ${theme.sizes.iconSmall}px`}; color: ${({ isActive, theme }) => (isActive ? theme.colors.textGold : theme.colors.textInverted)}; + border-radius: 4px; background-color: transparent; + &:hover { - color: ${({ isActive, theme }) => (isActive ? theme.colors.textGold : theme.colors.textInverted)}; + color: ${({ theme }) => theme.colors.textGold}; + background-color: rgba(145, 150, 155, 0.13); } ` diff --git a/centrifuge-app/src/components/PoolCard/index.tsx b/centrifuge-app/src/components/PoolCard/index.tsx index 8ed5b70083..62ed4e2866 100644 --- a/centrifuge-app/src/components/PoolCard/index.tsx +++ b/centrifuge-app/src/components/PoolCard/index.tsx @@ -173,7 +173,7 @@ export function PoolCard({ } }) .reverse() - }, [calculateApy, getTinlakeMinInvestment]) + }, [calculateApy, getTinlakeMinInvestment, isTinlakePool, metaData?.tranches, tinlakeObjKey, tranches]) return ( diff --git a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx index 1bedfd6d58..12c4882988 100644 --- a/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx +++ b/centrifuge-app/src/components/PoolOverview/TrancheTokenCards.tsx @@ -80,7 +80,7 @@ export const TrancheTokenCards = ({ ), }, ] - }, [pool, poolId, isTinlakePool, daysSinceCreation]) + }, [pool, poolId, isTinlakePool, daysSinceCreation, metadata]) const columns = useMemo(() => { return columnConfig.map((col, index) => { diff --git a/centrifuge-app/src/components/Report/PoolReportPage.tsx b/centrifuge-app/src/components/Report/PoolReportPage.tsx index 20db9daf21..178707993c 100644 --- a/centrifuge-app/src/components/Report/PoolReportPage.tsx +++ b/centrifuge-app/src/components/Report/PoolReportPage.tsx @@ -34,10 +34,6 @@ function PoolDetailReporting({ poolId, isReportingTab }: { poolId: string; isRep const pool = usePool(poolId) as Pool const contentWrapperRef = React.useRef(null) - if (!poolId || !pool) { - return - } - // We want to scroll within the table and not the page, // this way we can keep the filters on top of the page while scrolling on the table React.useEffect(() => { @@ -54,6 +50,10 @@ function PoolDetailReporting({ poolId, isReportingTab }: { poolId: string; isRep } }, [isReportingTab]) + if (!poolId || !pool) { + return + } + return (
}> From 2155682cd3be1dcb58b156620e039e4b27317492 Mon Sep 17 00:00:00 2001 From: katty barroso Date: Tue, 15 Oct 2024 10:00:01 +0200 Subject: [PATCH 08/12] Add realized unrealized values to invest/redeem drawer --- .../components/InvestRedeem/InvestRedeem.tsx | 63 ++++++++++++++++--- .../InvestRedeem/InvestRedeemDrawer.tsx | 33 +++++++--- .../src/components/PoolCard/index.tsx | 2 +- 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx index b266183461..92296da811 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx @@ -1,3 +1,4 @@ +import { CurrencyBalance } from '@centrifuge/centrifuge-js' import { ConnectionGuard, useGetNetworkName, useWallet } from '@centrifuge/centrifuge-react' import { Network } from '@centrifuge/centrifuge-react/dist/components/WalletProvider/types' import { useGetExplorerUrl } from '@centrifuge/centrifuge-react/dist/components/WalletProvider/utils' @@ -36,9 +37,18 @@ import { RedeemForm } from './RedeemForm' export type InvestRedeemProps = { poolId: string trancheId: string - metadata: PoolMetaDataPartial + metadata?: PoolMetaDataPartial } & InputProps +type HeaderProps = { + sumUnrealizedProfitAtMarketPrice?: CurrencyBalance + sumRealizedProfitFifoByPeriod?: CurrencyBalance +} & InputProps + +type InputProps = { + defaultView?: 'invest' | 'redeem' +} + // @ts-ignore const listFormatter = new Intl.ListFormat('en') @@ -73,7 +83,7 @@ export function InvestRedeem({ poolId, trancheId, ...rest }: InvestRedeemProps) > -
+
{!isTinlakePool && (connectedType === 'substrate' || isEvmOnSubstrate) && }