Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Redesign reports #2461

Merged
merged 9 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as React from 'react'
import { useParams } from 'react-router'
import { Bar, CartesianGrid, ComposedChart, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
import { ValueType } from 'recharts/types/component/DefaultTooltipContent'
import { useTheme } from 'styled-components'
import { getCSVDownloadUrl } from '../../../src/utils/getCSVDownloadUrl'
import { daysBetween, formatDate } from '../../utils/date'
Expand Down Expand Up @@ -46,6 +47,14 @@

type GraphDataItem = GraphDataItemWithType | GraphDataItemWithoutType

type CustomTickProps = {
x: number
y: number
payload: {
value: ValueType
}
}

const rangeFilters = [
{ value: 'all', label: 'All' },
{ value: '30d', label: '30 days' },
Expand Down Expand Up @@ -162,7 +171,7 @@
isToday: false,
}
}) || [],
[isSingleTranche, truncatedPoolStates, todayAssetValue, todayPrice, pool, range]

Check warning on line 174 in centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

View workflow job for this annotation

GitHub Actions / build-app

React Hook React.useMemo has unnecessary dependencies: 'isSingleTranche' and 'todayPrice'. Either exclude them or remove the dependency array

Check warning on line 174 in centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

React Hook React.useMemo has unnecessary dependencies: 'isSingleTranche' and 'todayPrice'. Either exclude them or remove the dependency array
)

const todayData = data.find((day) => day.isToday)
Expand Down Expand Up @@ -200,7 +209,7 @@
})

return getCSVDownloadUrl(filteredData as any)
}, [chartData, selectedTabIndex])

Check warning on line 212 in centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

View workflow job for this annotation

GitHub Actions / build-app

React Hook React.useMemo has an unnecessary dependency: 'selectedTabIndex'. Either exclude it or remove the dependency array

Check warning on line 212 in centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

React Hook React.useMemo has an unnecessary dependency: 'selectedTabIndex'. Either exclude it or remove the dependency array

if (truncatedPoolStates && truncatedPoolStates?.length < 1 && poolAge > 0)
return <Text variant="body2">No data available</Text>
Expand All @@ -221,7 +230,6 @@

return result
}

return (
<Stack gap={2} padding={20}>
<Stack flexDirection="row" justifyContent="space-between" alignItems="center" mb={12}>
Expand Down Expand Up @@ -471,7 +479,7 @@
<Box display="flex" justifyContent="space-between" alignItems="center">
<Box display="flex" justifyContent="space-evenly">
{graphData.map((item: GraphDataItem, index: number) => {
if (!item.show) return

Check warning on line 482 in centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

View workflow job for this annotation

GitHub Actions / build-app

Array.prototype.map() expects a return value from arrow function

Check warning on line 482 in centrifuge-app/src/components/Charts/PoolPerformanceChart.tsx

View workflow job for this annotation

GitHub Actions / ff-prod / build-app

Array.prototype.map() expects a return value from arrow function

const hasType = (item: GraphDataItem): item is GraphDataItemWithType => {
return (item as GraphDataItemWithType).type !== undefined
Expand Down Expand Up @@ -501,8 +509,17 @@
)
}

const CustomTick = ({ x, y, payload }: any) => {
export const CustomTick = ({ x, y, payload }: CustomTickProps) => {
const theme = useTheme()

let dateValue: Date | null = null

if (payload.value instanceof Date) {
dateValue = payload.value
} else if (typeof payload.value === 'string' || typeof payload.value === 'number') {
dateValue = new Date(payload.value)
}

return (
<g transform={`translate(${x},${y})`}>
<text
Expand All @@ -512,7 +529,7 @@
dy={16}
textAnchor="middle"
>
{new Date(payload.value).toLocaleString('en-US', { month: 'short' })}
{dateValue ? dateValue.toLocaleString('en-US', { month: 'short' }) : ''}
</text>
</g>
)
Expand Down
101 changes: 101 additions & 0 deletions centrifuge-app/src/components/Charts/SimpleBarChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { CurrencyBalance, CurrencyMetadata } from '@centrifuge/centrifuge-js'
import { Shelf, Text } from '@centrifuge/fabric'
import { Bar, BarChart, CartesianGrid, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
import { useTheme } from 'styled-components'
import { formatDate } from '../../../src/utils/date'
import { formatBalance, formatBalanceAbbreviated } from '../../../src/utils/formatting'
import { LoadBoundary } from '../LoadBoundary'
import { CustomTick } from './PoolPerformanceChart'
import { TooltipContainer, TooltipTitle } from './Tooltip'

type SimpleBarChartProps = {
currency?: CurrencyMetadata
data: { name: string; yAxis: number }[]
}

export const SimpleBarChart = ({ currency, data }: SimpleBarChartProps) => {
const theme = useTheme()

const getOneDayPerMonth = () => {
const seenMonths = new Set<string>()
const result: string[] = []

data.forEach((item) => {
const date = new Date(item.name)
const month = date.getMonth() + 1
const year = date.getFullYear()
const monthYear = `${year}-${month}`

if (!seenMonths.has(monthYear)) {
seenMonths.add(monthYear)
result.push(item.name)
}
})

return result
}

if (!data.length)
return (
<Shelf justifyContent="center">
<Text>No data available</Text>
</Shelf>
)

return (
<LoadBoundary>
<ResponsiveContainer width="100%" height={200}>
<BarChart width={500} height={300} data={data} barSize={10} barGap={10}>
<CartesianGrid stroke={theme.colors.borderPrimary} vertical={false} />
<XAxis
dy={4}
interval={0}
tickLine={false}
axisLine={false}
tickMargin={10}
type="category"
dataKey="name"
ticks={getOneDayPerMonth()}
tick={<CustomTick />}
angle={45}
/>
<YAxis
tickFormatter={(tick: number) => {
const balance = new CurrencyBalance(tick, currency?.decimals || 0)
return formatBalanceAbbreviated(balance, '', 0)
}}
tick={{ fontSize: 10, color: theme.colors.textPrimary }}
tickLine={false}
axisLine={false}
dataKey="yAxis"
/>
<ReferenceLine y={0} stroke={theme.colors.textSecondary} />

<Tooltip
cursor={false}
content={({ payload }) => {
if (payload && payload?.length > 0) {
return (
<TooltipContainer>
<TooltipTitle>{formatDate(payload[0].payload.name)}</TooltipTitle>
{payload.map((item) => (
<Text variant="body3">{formatBalance(item.value as number, currency)}</Text>
))}
</TooltipContainer>
)
}
}}
/>
<Bar
dataKey="yAxis"
name="yAxis"
fill={theme.colors.backgroundTertiary}
strokeWidth={0}
fillOpacity={1}
maxBarSize={20}
/>
</BarChart>
</ResponsiveContainer>
</LoadBoundary>
)
}
52 changes: 28 additions & 24 deletions centrifuge-app/src/components/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export type Column = {
align?: string
sortKey?: string
width?: string
isLabel?: boolean
}
const sorter = <T extends Record<string, any>>(data: Array<T>, order: OrderBy, sortKey?: string) => {
if (!sortKey) return data
Expand Down Expand Up @@ -149,33 +150,36 @@ export const DataTable = <T extends Record<string, any>>({
tabIndex={onRowClicked ? 0 : undefined}
>
{columns.map((col, index) => (
<DataCol variant="body2" align={col?.align} key={index}>
{col.cell(row, i)}
</DataCol>
))}
</DataRow>
))}
{sortedAndPaginatedData?.map((row, i) => (
<DataRow
data-testId={`data-table-row-${i}-${groupIndex ?? 0}`}
hoverable={hoverable}
as={onRowClicked ? Link : 'div'}
to={onRowClicked ? onRowClicked(row) : undefined}
key={keyField ? row[keyField] : i}
tabIndex={onRowClicked ? 0 : undefined}
>
{columns.map((col, index) => (
<DataCol
data-testId={`data-table-col-${i}-${groupIndex ?? 0}-${col.header}`}
variant="body2"
align={col?.align}
key={index}
>
<DataCol variant="body2" align={col?.align} key={index} isLabel={col.isLabel}>
{col.cell(row, i)}
</DataCol>
))}
</DataRow>
))}
{sortedAndPaginatedData?.map((row, i) => {
return (
<DataRow
data-testId={`data-table-row-${i}-${groupIndex ?? 0}`}
hoverable={hoverable}
as={onRowClicked ? Link : 'div'}
to={onRowClicked ? onRowClicked(row) : undefined}
key={keyField ? row[keyField] : i}
tabIndex={onRowClicked ? 0 : undefined}
>
{columns.map((col, index) => (
<DataCol
data-testId={`data-table-col-${i}-${groupIndex ?? 0}-${col.header}`}
variant="body2"
align={col?.align}
key={index}
isLabel={col.isLabel}
>
{col.cell(row, i)}
</DataCol>
))}
</DataRow>
)
})}
{/* summary row is not included in sorting */}
{summary && (
<DataRow data-testId={`row-summary-${groupIndex ?? 0}`}>
Expand Down Expand Up @@ -241,8 +245,8 @@ export const DataRow = styled(Row)<any>`
})}
`

export const DataCol = styled(Text)<{ align: Column['align'] }>`
background: initial;
export const DataCol = styled(Text)<{ align: Column['align']; isLabel?: boolean }>`
background: ${({ isLabel, theme }) => (isLabel ? theme.colors.backgroundSecondary : 'initial')};
border: none;
padding: 8px 16px;
display: flex;
Expand Down
8 changes: 4 additions & 4 deletions centrifuge-app/src/components/IssuerSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ type IssuerSectionProps = {
}

const reportLinks = [
{ label: 'Balance sheet', href: '/balance-sheet', icon: <IconBalanceSheet /> },
{ label: 'Profit & loss', href: '/profit-and-loss', icon: <IconProfitAndLoss /> },
{ label: 'Cashflow statement', href: '/cash-flow-statement', icon: <IconCashflow /> },
{ label: 'Balance sheet', href: '/balance-sheet', icon: <IconBalanceSheet color="backgroundPrimary" /> },
{ label: 'Profit & loss', href: '/profit-and-loss', icon: <IconProfitAndLoss color="backgroundPrimary" /> },
{ label: 'Cashflow statement', href: '/cash-flow-statement', icon: <IconCashflow color="backgroundPrimary" /> },
]

const StyledRouterTextLink = styled(RouterTextLink)`
Expand Down Expand Up @@ -78,7 +78,7 @@ export function ReportDetails({ metadata }: IssuerSectionProps) {
{link.label}
</StyledRouterTextLink>
</Box>
<IconChevronRight color="white" />
<IconChevronRight color="backgroundPrimary" />
</Box>
))}
</Box>
Expand Down
32 changes: 22 additions & 10 deletions centrifuge-app/src/components/LayoutBase/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FooterContainer,
Inner,
LogoContainer,
MobileBar,
Root,
ToolbarContainer,
WalletContainer,
Expand All @@ -30,19 +31,30 @@ export function LayoutBase(): JSX.Element {
</WalletInner>
</WalletPositioner>
</WalletContainer>
<Inner>
<LogoContainer>
<LogoLink />
</LogoContainer>
<ToolbarContainer as="aside">
<Menu />
</ToolbarContainer>
{isMedium && (
{isMedium ? (
<Inner>
<LogoContainer>
<LogoLink />
</LogoContainer>
<ToolbarContainer as="aside">
<Menu />
</ToolbarContainer>
<FooterContainer>
<Footer />
</FooterContainer>
)}
</Inner>
</Inner>
) : (
<>
<LogoContainer>
<LogoLink />
</LogoContainer>
<MobileBar>
<ToolbarContainer as="aside">
<Menu />
</ToolbarContainer>
</MobileBar>
</>
)}
<ContentWrapper>
<Outlet />
</ContentWrapper>
Expand Down
Loading
Loading