Skip to content

Commit

Permalink
Addsort buttons to table and view all button
Browse files Browse the repository at this point in the history
  • Loading branch information
sophialittlejohn committed Sep 28, 2023
1 parent 9e6e567 commit d9e3cf8
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ const states: {
}
} = {
INVEST_ORDER_UPDATE: {
label: 'Pending invest',
label: 'Invest order placed',
status: 'default',
},
REDEEM_ORDER_UPDATE: {
label: 'Pending redemption',
label: 'Redeem order placed',
status: 'default',
},
INVEST_ORDER_CANCEL: {
Expand All @@ -29,11 +29,11 @@ const states: {
status: 'default',
},
INVEST_EXECUTION: {
label: 'Invest',
label: 'Invest executed',
status: 'ok',
},
REDEEM_EXECUTION: {
label: 'Redeem',
label: 'Redeem executed',
status: 'info',
},
TRANSFER_IN: {
Expand Down
136 changes: 110 additions & 26 deletions centrifuge-app/src/components/Portfolio/Transactions.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import { BorrowerTransactionType, CurrencyBalance, InvestorTransactionType, Pool } from '@centrifuge/centrifuge-js'
import {
BorrowerTransactionType,
CurrencyBalance,
InvestorTransactionType,
Pool,
TokenBalance,
} from '@centrifuge/centrifuge-js'
import { useCentrifugeUtils } from '@centrifuge/centrifuge-react'
import { Box, Grid, IconExternalLink, Stack, Text } from '@centrifuge/fabric'
import {
AnchorButton,
Box,
Grid,
IconChevronDown,
IconChevronUp,
IconExternalLink,
IconEye,
Shelf,
Stack,
Text,
} from '@centrifuge/fabric'
import * as React from 'react'
import { Link, useRouteMatch } from 'react-router-dom'
import { useRouteMatch } from 'react-router-dom'
import styled from 'styled-components'
import { formatDate } from '../../utils/date'
import { formatBalanceAbbreviated } from '../../utils/formatting'
import { formatBalance } from '../../utils/formatting'
import { useAddress } from '../../utils/useAddress'
import { usePool, usePoolMetadata, useTransactionsByAddress } from '../../utils/usePools'
import { TransactionTypeChip } from './TransactionTypeChip'
Expand All @@ -22,20 +40,34 @@ export function Transactions({ count, txTypes }: AddressTransactionsProps) {
const address = useAddress()
const transactions = useTransactionsByAddress(formatAddress(address || ''))
const match = useRouteMatch('/portfolio/transactions')

const investorTransactions =
transactions?.investorTransactions
.filter((tx) => (txTypes ? txTypes?.includes(tx.type) : tx))
.map((tx) => {
return {
date: new Date(tx.timestamp).getTime(),
type: tx.type,
amount: tx.tokenAmount,
poolId: tx.poolId,
hash: tx.hash,
trancheId: tx.trancheId,
}
}) || []
const [sortKey, setSortKey] = React.useState<'date' | 'amount'>('date')
const [sortOrder, setSortOrder] = React.useState<'asc' | 'desc'>('desc')

const investorTransactions = React.useMemo(() => {
const txs =
transactions?.investorTransactions
.filter((tx) => (txTypes ? txTypes?.includes(tx.type) : tx))
.map((tx) => {
return {
date: new Date(tx.timestamp).getTime(),
type: tx.type,
poolId: tx.poolId,
hash: tx.hash,
trancheId: tx.trancheId,
amount: tx.currencyAmount,
}
})
.sort((a, b) => {
if (sortKey === 'date') {
return new Date(b.date).getTime() - new Date(a.date).getTime()
} else if (sortKey === 'amount') {
return b.amount.toDecimal().minus(a.amount.toDecimal()).toNumber()
} else {
return 1
}
}) || []
return sortOrder === 'asc' ? txs : txs.reverse()
}, [sortKey, transactions, sortOrder])

Check warning on line 70 in centrifuge-app/src/components/Portfolio/Transactions.tsx

View workflow job for this annotation

GitHub Actions / build-app

React Hook React.useMemo has a missing dependency: 'txTypes'. Either include it or remove the dependency array

return !!investorTransactions.slice(0, count ?? investorTransactions.length) ? (
<Stack as="article" gap={2}>
Expand All @@ -46,14 +78,52 @@ export function Transactions({ count, txTypes }: AddressTransactionsProps) {
<Stack>
<Grid gridTemplateColumns={TRANSACTION_CARD_COLUMNS} gap={TRANSACTION_CARD_GAP}>
<Text variant="body3">Action</Text>

<Text variant="body3">Transaction date</Text>
<SortButton
as="button"
onClick={() => {
setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')
setSortKey('date')
}}
gap={1}
>
<Text variant="body3">Transaction date</Text>
<Stack as="span" width="1em" style={{ marginTop: '-.3em' }}>
<IconChevronUp
size="1em"
color={sortKey === 'date' && sortOrder === 'asc' ? 'textSelected' : 'textSecondary'}
/>
<IconChevronDown
size="1em"
color={sortKey === 'date' && sortOrder === 'desc' ? 'textSelected' : 'textSecondary'}
style={{ marginTop: '-.4em' }}
/>
</Stack>
</SortButton>

<Text variant="body3">Token</Text>

<Box justifySelf="end">
<SortButton
as="button"
onClick={() => {
setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc')
setSortKey('amount')
}}
gap={1}
justifyContent="flex-end"
>
<Text variant="body3">Amount</Text>
</Box>
<Stack as="span" width="1em" style={{ marginTop: '-.3em' }}>
<IconChevronUp
size="1em"
color={sortKey === 'amount' && sortOrder === 'asc' ? 'textSelected' : 'textSecondary'}
/>
<IconChevronDown
size="1em"
color={sortKey === 'amount' && sortOrder === 'desc' ? 'textSelected' : 'textSecondary'}
style={{ marginTop: '-.4em' }}
/>
</Stack>
</SortButton>
</Grid>

<Stack as="ul" role="list">
Expand All @@ -64,20 +134,34 @@ export function Transactions({ count, txTypes }: AddressTransactionsProps) {
))}
</Stack>
</Stack>
{match ? null : <Link to="portfolio/transactions">View all</Link>}
<Box>
{match ? null : (
<AnchorButton variant="tertiary" href="portfolio/transactions" icon={IconEye}>
View all
</AnchorButton>
)}
</Box>
</Stack>
) : null
}

export type TransactionCardProps = {
date: number
type: InvestorTransactionType | BorrowerTransactionType
amount: CurrencyBalance
amount: CurrencyBalance | TokenBalance
poolId: string
hash: string
trancheId?: string
}

const SortButton = styled(Shelf)`
background: initial;
border: none;
cursor: pointer;
display: inline-flex;
align-items: flex-start;
`

export function TransactionListItem({ date, type, amount, poolId, hash, trancheId }: TransactionCardProps) {
const pool = usePool(poolId) as Pool
const { data } = usePoolMetadata(pool)
Expand Down Expand Up @@ -112,7 +196,7 @@ export function TransactionListItem({ date, type, amount, poolId, hash, trancheI

<Stack gap={1}>
<Text as="span" variant="interactive2">
{!!token ? token.currency?.name.split(data.pool?.name || '') : data.pool?.name}
{!!token ? token?.currency?.name.split(`${data?.pool?.name} ` || '').at(-1) : data.pool?.name}
</Text>
{!!token && (
<Text as="span" variant="interactive2" color="textDisabled">
Expand All @@ -123,7 +207,7 @@ export function TransactionListItem({ date, type, amount, poolId, hash, trancheI

<Box justifySelf="end">
<Text as="span" variant="interactive2">
{formatBalanceAbbreviated(amount, pool.currency.symbol)}
{formatBalance(amount.toDecimal(), pool.currency.symbol)}
</Text>
</Box>

Expand Down
2 changes: 1 addition & 1 deletion centrifuge-app/src/pages/Portfolio/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function PortfolioPage() {
}

function Portfolio() {
const address = useAddress()
const address = useAddress('substrate')
const theme = useTheme()

if (!address) {
Expand Down
33 changes: 17 additions & 16 deletions centrifuge-js/src/modules/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2047,25 +2047,26 @@ export function getPoolsModule(inst: Centrifuge) {

return $query.pipe(
switchMap((data) => {
const $investorTransactions = from(data?.investorTransactions.nodes || [])
// .pipe(distinct(({ hash }) => hash))
.pipe(
mergeMap((entry) => {
return getPoolCurrency([entry.poolId]).pipe(
map((poolCurrency) => ({
...entry,
tokenAmount: new CurrencyBalance(entry.tokenAmount || 0, poolCurrency.decimals),
tokenPrice: new Price(entry.tokenPrice || 0),
currencyAmount: new CurrencyBalance(entry.currencyAmount || 0, poolCurrency.decimals),
trancheId: entry.trancheId.split('-')[1],
}))
)
}),
toArray()
)
const $investorTransactions = from(data?.investorTransactions.nodes || []).pipe(
mergeMap((entry) => {
return getPoolCurrency([entry.poolId]).pipe(
map((poolCurrency) => ({
...entry,
tokenAmount: new TokenBalance(entry.tokenAmount || 0, poolCurrency.decimals),
tokenPrice: new Price(entry.tokenPrice || 0),
currencyAmount: new CurrencyBalance(entry.currencyAmount || 0, poolCurrency.decimals),
trancheId: entry.trancheId.split('-')[1],
}))
)
}),
toArray()
)

return forkJoin([$investorTransactions]).pipe(
map(([investorTransactions]) => {
investorTransactions.sort((a, b) => {
return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
})
return {
investorTransactions,
}
Expand Down

0 comments on commit d9e3cf8

Please sign in to comment.