From 15fba02222e73024cd7a4f21581554ab5b29cb7d Mon Sep 17 00:00:00 2001 From: katty barroso Date: Thu, 12 Dec 2024 15:06:19 +0100 Subject: [PATCH 1/2] wip --- .../src/assets/images/prime_page_image.svg | 9 ++ centrifuge-app/src/pages/Prime/index.tsx | 106 ++++++++++-------- fabric/src/theme/tokens/colors.ts | 2 +- fabric/src/theme/tokens/theme.ts | 1 + fabric/src/theme/types.ts | 3 +- 5 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 centrifuge-app/src/assets/images/prime_page_image.svg diff --git a/centrifuge-app/src/assets/images/prime_page_image.svg b/centrifuge-app/src/assets/images/prime_page_image.svg new file mode 100644 index 0000000000..a64d1f53e1 --- /dev/null +++ b/centrifuge-app/src/assets/images/prime_page_image.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/centrifuge-app/src/pages/Prime/index.tsx b/centrifuge-app/src/pages/Prime/index.tsx index 7ffbccba0d..ef555e2965 100644 --- a/centrifuge-app/src/pages/Prime/index.tsx +++ b/centrifuge-app/src/pages/Prime/index.tsx @@ -1,6 +1,9 @@ import { CurrencyBalance, addressToHex } from '@centrifuge/centrifuge-js' import { useCentrifugeUtils, useGetNetworkName } from '@centrifuge/centrifuge-react' -import { AnchorButton, Box, IconExternalLink, Shelf, Text, TextWithPlaceholder } from '@centrifuge/fabric' +import { Box, Grid, IconExternalLink, IconGlobe, Shelf, Text, TextWithPlaceholder } from '@centrifuge/fabric' +import { useTheme } from 'styled-components' +import { AnchorTextLink } from '../../../src/components/TextLink' +import primePageImage from '../../assets/images/prime_page_image.svg' import { Column, DataTable, FilterableTableHeader, SortableTableHeader } from '../../components/DataTable' import { LayoutSection } from '../../components/LayoutBase/LayoutSection' import { formatDate } from '../../utils/date' @@ -15,29 +18,59 @@ export default function PrimePage() { } function Prime() { + const theme = useTheme() return ( <> - - Centrifuge Prime - - - Centrifuge Prime was built to meet the needs of large decentralized organizations and protocols. Through - Centrifuge Prime, DeFi native organizations can integrate with the largest financial markets in the world - and take advantage of real yields from real economic activity - all onchain. Assets tailored to your needs, - processes adapted to your governance, and all through decentralized rails. - - - - + + - Go to website - + + + + Centrifuge Prime + + + + + Centrifuge Prime was built to meet the needs of large decentralized organizations and protocols. Through + Centrifuge Prime, DeFi native organizations can integrate with the largest financial markets in the world + and take advantage of real yields from real economic activity - all onchain. Assets tailored to your + needs, processes adapted to your governance, and all through decentralized rails. + + + + Go to website + + + + + + + + + ) @@ -134,30 +167,6 @@ function DaoPortfoliosTable() { trancheBalances[trancheId] = { balance, tokenPrice } } }) - // const trancheBalances = !!account - // ? Object.fromEntries( - // account.trancheBalances.nodes.map((tranche: any) => { - // const pool = pools?.find((p) => p.id === tranche.poolId) - // const decimals = pool?.currency.decimals ?? 18 - // const tokenPrice = pool?.tranches.find((t) => tranche.trancheId.endsWith(t.id))?.tokenPrice?.toFloat() ?? 1 - // let balance = new CurrencyBalance( - // new BN(tranche.claimableTrancheTokens).add(new BN(tranche.pendingRedeemTrancheTokens)), - // decimals - // ).toFloat() - - // const subqueryCurrencies = account?.currencyBalances.nodes.filter( - // (b: any) => b.currency.trancheId && b.currency.trancheId === tranche.trancheId - // ) - // if (subqueryCurrencies.length) { - // balance += subqueryCurrencies.reduce( - // (acc: number, cur: any) => acc + new CurrencyBalance(cur.amount, decimals).toFloat(), - // 0 - // ) - // } - // return [tranche.trancheId.split('-')[1], { balance, tokenPrice }] - // }) - // ) - // : {} const totalValue = Object.values(trancheBalances)?.reduce( (acc, { balance, tokenPrice }) => acc + balance * tokenPrice, 0 @@ -184,6 +193,7 @@ function DaoPortfoliosTable() { {row.name} ), + width: '2fr', }, { align: 'left', @@ -196,8 +206,10 @@ function DaoPortfoliosTable() { /> ), cell: (row: Row) => {getNetworkName(row.network)}, + width: '2fr', }, { + align: 'left', header: , cell: (row: Row) => ( @@ -205,6 +217,7 @@ function DaoPortfoliosTable() { ), sortKey: 'value', + width: '2fr', }, { align: 'left', @@ -219,7 +232,10 @@ function DaoPortfoliosTable() { ] return ( - + + + Portfolios + `/prime/${row.slug}`} /> - + ) } diff --git a/fabric/src/theme/tokens/colors.ts b/fabric/src/theme/tokens/colors.ts index ba4cf42d8a..84c6e9d42e 100644 --- a/fabric/src/theme/tokens/colors.ts +++ b/fabric/src/theme/tokens/colors.ts @@ -2,7 +2,7 @@ export const black = '#252B34' export const gold = '#FFC012' export const grayScale = { - 10: '#cfcfcf33', + 10: '#F9FAFB', 50: '#F6F6F6', 100: '#E7E7E7', 300: '#CFCFCF', diff --git a/fabric/src/theme/tokens/theme.ts b/fabric/src/theme/tokens/theme.ts index 73f8be47db..51071ea433 100644 --- a/fabric/src/theme/tokens/theme.ts +++ b/fabric/src/theme/tokens/theme.ts @@ -30,6 +30,7 @@ const colors = { backgroundInput: 'white', backgroundThumbnail: grayScale[500], backgroundInverted: grayScale[800], + backgroundLight: grayScale[10], borderPrimary: grayScale[100], borderSecondary: 'rgba(207, 207, 207, 0.50)', diff --git a/fabric/src/theme/types.ts b/fabric/src/theme/types.ts index 52d0023606..9a2623b3ca 100644 --- a/fabric/src/theme/types.ts +++ b/fabric/src/theme/types.ts @@ -27,7 +27,8 @@ type BackgroundColorName = `background${ | 'Thumbnail' | 'AccentPrimary' | 'AccentSecondary' - | 'Inverted'}` + | 'Inverted' + | 'Light'}` type ButtonColorName = | `${'background' | 'text' | 'border'}Button${'Primary' | 'Secondary' | 'Tertiary' | 'Inverted'}${ | '' From b9f71dbb44b75bfc8f3e6cdb837ee36daec0467d Mon Sep 17 00:00:00 2001 From: katty barroso Date: Tue, 17 Dec 2024 15:16:47 +0100 Subject: [PATCH 2/2] wip --- .../src/components/AssetSummary.tsx | 12 +- centrifuge-app/src/components/BackButton.tsx | 54 +++++++++ .../src/components/Charts/SimpleLineChart.tsx | 67 ++++++++++- centrifuge-app/src/pages/Loan/index.tsx | 51 +-------- centrifuge-app/src/pages/Prime/Detail.tsx | 104 +++++++++++++----- 5 files changed, 209 insertions(+), 79 deletions(-) create mode 100644 centrifuge-app/src/components/BackButton.tsx diff --git a/centrifuge-app/src/components/AssetSummary.tsx b/centrifuge-app/src/components/AssetSummary.tsx index a3cb456af4..bfaa4f4021 100644 --- a/centrifuge-app/src/components/AssetSummary.tsx +++ b/centrifuge-app/src/components/AssetSummary.tsx @@ -1,4 +1,4 @@ -import { Shelf, Stack, Text } from '@centrifuge/fabric' +import { Box, Shelf, Stack, Text } from '@centrifuge/fabric' import * as React from 'react' import { useTheme } from 'styled-components' @@ -7,6 +7,7 @@ type Props = { label: React.ReactNode value: React.ReactNode heading: boolean + children?: React.ReactNode }[] children?: React.ReactNode } @@ -22,12 +23,17 @@ export function AssetSummary({ data, children }: Props) { mx={[2, 2, 2, 2, 5]} > - {data?.map(({ label, value, heading }, index) => ( + {data?.map(({ label, value, heading, children }, index) => ( {label} - {value} + + + {value} + + {children && children} + ))} {children} diff --git a/centrifuge-app/src/components/BackButton.tsx b/centrifuge-app/src/components/BackButton.tsx new file mode 100644 index 0000000000..e47b636cb0 --- /dev/null +++ b/centrifuge-app/src/components/BackButton.tsx @@ -0,0 +1,54 @@ +import { Box, IconArrowLeft, Text } from '@centrifuge/fabric' +import { ReactNode } from 'react' +import styled from 'styled-components' +import { RouterLinkButton } from './RouterLinkButton' + +const StyledRouterLinkButton = styled(RouterLinkButton)` + margin-left: 14px; + border-radius: 50%; + margin: 0px; + padding: 0px; + width: fit-content; + margin-left: 30px; + border: 4px solid transparent; + width: 30px; + height: 30px; + display: flex; + justify-content: center; + align-items: center; + + > span { + width: 34px; + border: 4px solid transparent; + } + &:hover { + background-color: ${({ theme }) => theme.colors.backgroundSecondary}; + span { + color: ${({ theme }) => theme.colors.textPrimary}; + } + } +` + +export const BackButton = ({ + to, + children, + label, + align, +}: { + to: string + children?: ReactNode + label: string + align?: string +}) => { + return ( + + } variant="tertiary" /> + + + {label} + + {children} + + + ) +} diff --git a/centrifuge-app/src/components/Charts/SimpleLineChart.tsx b/centrifuge-app/src/components/Charts/SimpleLineChart.tsx index 561af846c2..cea919dff6 100644 --- a/centrifuge-app/src/components/Charts/SimpleLineChart.tsx +++ b/centrifuge-app/src/components/Charts/SimpleLineChart.tsx @@ -1,11 +1,19 @@ import { CurrencyBalance, CurrencyMetadata } from '@centrifuge/centrifuge-js' -import { Card, Shelf, Stack, Text } from '@centrifuge/fabric' +import { Box, Card, Select, Shelf, Stack, Text } from '@centrifuge/fabric' +import { useState } from 'react' import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts' import { useTheme } from 'styled-components' import { formatDate } from '../../utils/date' import { formatBalance, formatBalanceAbbreviated } from '../../utils/formatting' import { TooltipContainer, TooltipTitle } from './Tooltip' +const rangeFilters = [ + { value: '30d', label: '30 days' }, + { value: '90d', label: '90 days' }, + { value: 'ytd', label: 'Year to date' }, + { value: 'all', label: 'All' }, +] + type ChartData = { name: string yAxis: Number @@ -14,21 +22,65 @@ type ChartData = { interface Props { data: ChartData[] currency?: CurrencyMetadata + tooltip?: (value: any) => { value: any; label: string } + withFilters?: boolean + filters: { + type: 'default' | { value: string; label: string } + title: string + legend: [ + { + label: string + color: string + value: string + } + ] + } } -export const SimpleLineChart = ({ data, currency }: Props) => { +const Dot = ({ color }: { color: string }) => ( + +) + +// We use the chart for pages: asset, prime, portfolio +export const SimpleLineChart = ({ data, currency, tooltip, filters }: Props) => { const theme = useTheme() const chartColor = theme.colors.accentPrimary + const [range, setRange] = useState<(typeof rangeFilters)[number]>(rangeFilters[0]) + + const toggleRange = (e: React.ChangeEvent) => { + const value = e.target.value + const range = rangeFilters.find((range) => range.value === value) + setRange(range ?? rangeFilters[0]) + } + + console.log(data) + return ( + {filters && {filters.title}} + {filters && ( + + {filters.legend.map((legend) => ( + + + + + {legend.label} + + + {legend.value} + + ))} +