diff --git a/centrifuge-app/src/components/Charts/AssetPerformanceChart.tsx b/centrifuge-app/src/components/Charts/AssetPerformanceChart.tsx index fe30d78e19..849deae06e 100644 --- a/centrifuge-app/src/components/Charts/AssetPerformanceChart.tsx +++ b/centrifuge-app/src/components/Charts/AssetPerformanceChart.tsx @@ -1,8 +1,8 @@ import { Pool } from '@centrifuge/centrifuge-js' -import { Box, Card, Shelf, Spinner, Stack, Text } from '@centrifuge/fabric' +import { AnchorButton, Box, Card, IconDownload, Shelf, Spinner, Stack, Tabs, TabsItem, Text } from '@centrifuge/fabric' import * as React from 'react' import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts' -import styled, { useTheme } from 'styled-components' +import { useTheme } from 'styled-components' import { formatDate } from '../../utils/date' import { formatBalance, formatBalanceAbbreviated } from '../../utils/formatting' import { TinlakePool } from '../../utils/tinlake/useTinlakePools' @@ -24,30 +24,13 @@ interface Props { loanId: string } -const FilterButton = styled(Stack)` - &:hover { - cursor: pointer; - } -` - -const filterOptions = [ - { value: 'price', label: 'Price' }, - { value: 'value', label: 'Asset value' }, -] as const - function AssetPerformanceChart({ pool, poolId, loanId }: Props) { const theme = useTheme() const chartColor = theme.colors.accentPrimary const asset = useLoan(poolId, loanId) const assetSnapshots = useAssetSnapshots(poolId, loanId) - const [activeFilter, setActiveFilter] = React.useState<(typeof filterOptions)[number]>(filterOptions[0]) - - React.useEffect(() => { - if (assetSnapshots && assetSnapshots[0]?.currentPrice?.toString() === '0') { - setActiveFilter(filterOptions[1]) - } - }, [assetSnapshots]) + const [selectedTabIndex, setSelectedTabIndex] = React.useState(0) const data: ChartData[] = React.useMemo(() => { if (!asset || !assetSnapshots) return [] @@ -139,17 +122,44 @@ function AssetPerformanceChart({ pool, poolId, loanId }: Props) { if (!assetSnapshots) return return ( - + - - - {asset && 'valuationMethod' in asset.pricing && asset?.pricing.valuationMethod !== 'cash' - ? 'Asset performance' - : 'Cash balance'} - - - ({pool.currency.name ?? 'USD'}) - + + + + {asset && 'valuationMethod' in asset.pricing && asset?.pricing.valuationMethod !== 'cash' + ? 'Asset performance' + : 'Cash balance'} + + + ({pool.currency.name ?? 'USD'}) + + + {!(assetSnapshots && assetSnapshots[0]?.currentPrice?.toString() === '0') && ( + + + {data.length > 0 && ( + setSelectedTabIndex(index)}> + + Price + + + Asset value + + + )} + + + )} + + Download + {isChartEmpty && ( @@ -158,31 +168,6 @@ function AssetPerformanceChart({ pool, poolId, loanId }: Props) { )} - {!(assetSnapshots && assetSnapshots[0]?.currentPrice?.toString() === '0') && ( - - - {data.length > 0 && - filterOptions.map((filter, index) => ( - - setActiveFilter(filter)}> - - {filter.label} - - - - {index !== filterOptions.length - 1 && ( - - )} - - ))} - - - )} - {data?.length ? ( @@ -211,7 +196,7 @@ function AssetPerformanceChart({ pool, poolId, loanId }: Props) { tickLine={false} style={{ fontSize: '10px', fill: theme.colors.textSecondary }} tickFormatter={(tick: number) => formatBalanceAbbreviated(tick, '', 2)} - domain={activeFilter.value === 'price' ? priceRange : [0, 'auto']} + domain={selectedTabIndex === 0 ? priceRange : [0, 'auto']} width={90} /> @@ -252,7 +237,7 @@ function AssetPerformanceChart({ pool, poolId, loanId }: Props) { }} /> - {activeFilter.value === 'price' && ( + {selectedTabIndex === 0 && ( )} - {activeFilter.value === 'price' && ( + {selectedTabIndex === 0 && ( )} - {activeFilter.value === 'value' && ( + {selectedTabIndex === 1 && ( )} - {activeFilter.value === 'value' && ( + {selectedTabIndex === 1 && ( - - Transaction history - + Transaction history {transactions?.length! > 8 && preview && ( diff --git a/centrifuge-app/src/pages/Loan/HoldingsValues.tsx b/centrifuge-app/src/pages/Loan/HoldingsValues.tsx index 8f9146f16a..d3ba229f84 100644 --- a/centrifuge-app/src/pages/Loan/HoldingsValues.tsx +++ b/centrifuge-app/src/pages/Loan/HoldingsValues.tsx @@ -74,11 +74,9 @@ export function HoldingsValues({ pool, transactions, currentFace, pricing }: Pro ] return ( - + - - Holdings - + Holdings diff --git a/centrifuge-app/src/pages/Loan/KeyMetrics.tsx b/centrifuge-app/src/pages/Loan/KeyMetrics.tsx index 3d5bb53459..ef9838db29 100644 --- a/centrifuge-app/src/pages/Loan/KeyMetrics.tsx +++ b/centrifuge-app/src/pages/Loan/KeyMetrics.tsx @@ -155,11 +155,9 @@ export function KeyMetrics({ pool, loan }: Props) { ] return ( - + - - Key metrics - + Key metrics diff --git a/centrifuge-app/src/pages/Loan/MetricsTable.tsx b/centrifuge-app/src/pages/Loan/MetricsTable.tsx index 431ebc3425..dedc335393 100644 --- a/centrifuge-app/src/pages/Loan/MetricsTable.tsx +++ b/centrifuge-app/src/pages/Loan/MetricsTable.tsx @@ -12,7 +12,7 @@ type Props = { export function MetricsTable({ metrics }: Props) { return ( - + {metrics.map(({ label, value }, index) => { const multirow = value && value.length > 20 const asLink = value && /^(https?:\/\/[^\s]+)$/.test(value) @@ -33,25 +33,21 @@ export function MetricsTable({ metrics }: Props) { } : {} - const combinedStyle: React.CSSProperties = { ...defaultStyle, ...multiRowStyle } + const combinedStyle: React.CSSProperties = { ...defaultStyle, ...multiRowStyle, textAlign: 'right' } return ( - + {label} - + {asLink ? {value} : value} diff --git a/centrifuge-app/src/pages/Loan/PricingValues.tsx b/centrifuge-app/src/pages/Loan/PricingValues.tsx index 4d095fa314..9ac7e84218 100644 --- a/centrifuge-app/src/pages/Loan/PricingValues.tsx +++ b/centrifuge-app/src/pages/Loan/PricingValues.tsx @@ -59,11 +59,9 @@ export function PricingValues({ loan, pool }: Props) { const accruedPrice = 'currentPrice' in loan && loan.currentPrice return ( - + - - Pricing - + Pricing , + label: , value: pricing.withLinearPricing ? 'Enabled' : 'Disabled', }, ...(loan.status === 'Active' && loan.outstandingDebt.toDecimal().lte(0) @@ -102,9 +100,7 @@ export function PricingValues({ loan, pool }: Props) { return ( - - Pricing - + Pricing )} - {'valuationMethod' in loan.pricing && loan.pricing.valuationMethod !== 'cash' && ( + {isCash && ( }> @@ -226,11 +227,9 @@ function Loan() { if (!isPublic) return null return ( }> - + - - {section.name} - + {section.name} {borrowerAssetTransactions?.length ? ( - 'valuationMethod' in loan.pricing && loan.pricing.valuationMethod === 'cash' ? ( + isCash ? ( - - Transaction history - - + Transaction history , diff --git a/fabric/src/components/Card/index.ts b/fabric/src/components/Card/index.ts index 7b4afd6639..79e5894cdf 100644 --- a/fabric/src/components/Card/index.ts +++ b/fabric/src/components/Card/index.ts @@ -3,21 +3,20 @@ import styled from 'styled-components' import { Box, BoxProps } from '../Box' type Props = { - variant?: 'default' | 'interactive' | 'overlay' + variant?: 'default' | 'interactive' | 'overlay' | 'secondary' backgroundColor?: string - borderColor?: string } export type CardProps = Props & Omit -export const Card = styled(Box)(({ variant = 'default', backgroundColor, borderColor }) => +export const Card = styled(Box)(({ variant = 'default', backgroundColor }) => css({ bg: backgroundColor ?? 'white', borderRadius: 'card', - borderWidth: variant === 'default' && !backgroundColor ? 1 : 0, + borderWidth: variant === 'default' || (variant === 'secondary' && !backgroundColor) ? 1 : 0, borderStyle: 'solid', - borderColor: borderColor ?? 'borderPrimary', + borderColor: variant === 'secondary' ? 'borderSecondary' : 'borderPrimary', boxShadow: variant === 'interactive' ? 'cardInteractive' : variant === 'overlay' ? 'cardOverlay' : undefined, transition: 'box-shadow 100ms ease',