Skip to content

Commit

Permalink
💱 CRT transaction table component (Joystream#4752)
Browse files Browse the repository at this point in the history
* Extract a DateTimeBlock component from TablePaymentsHistory

* Add the CrtTransactionsTable component

* Fix stories globaly
  • Loading branch information
thesan authored and WRadoslaw committed Apr 22, 2024
1 parent 2ebed81 commit da77aa8
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Meta } from '@storybook/react'

import { DateTimeBlockProps, DateTimeBlock as _DateTimeBlock } from './DateTimeBlock'

export default {
title: 'crt/DateTimeBlock',
component: _DateTimeBlock,
args: {
date: new Date(),
},
} as Meta<DateTimeBlockProps>

export const DateTimeBlock = {}
21 changes: 21 additions & 0 deletions packages/atlas/src/components/DateTimeBlock/DateTimeBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { FC } from 'react'

import { Text } from '@/components/Text'
import { useBlockTimeEstimation } from '@/hooks/useBlockTimeEstimation'
import { formatNumber } from '@/utils/number'
import { formatDateTime } from '@/utils/time'

export type DateTimeBlockProps = { date: Date }
export const DateTimeBlock: FC<DateTimeBlockProps> = ({ date }) => {
const { convertMsTimestampToBlock } = useBlockTimeEstimation()
return (
<>
<Text as="p" variant="t200-strong">
{formatDateTime(date)}
</Text>
<Text as="p" variant="t100" margin={{ top: 1 }} color="colorText">
{formatNumber(convertMsTimestampToBlock(date.getTime()) || 0)} block
</Text>
</>
)
}
1 change: 1 addition & 0 deletions packages/atlas/src/components/DateTimeBlock/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './DateTimeBlock'
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FC, useEffect, useMemo, useRef, useState } from 'react'
import { useMemberships } from '@/api/hooks/membership'
import { SvgJoystreamLogoShort } from '@/assets/logos'
import { Avatar } from '@/components/Avatar'
import { DateTimeBlock } from '@/components/DateTimeBlock'
import { Table, TableProps } from '@/components/Table'
import { Text } from '@/components/Text'
import { TextButton } from '@/components/_buttons/Button'
Expand All @@ -12,8 +13,6 @@ import { absoluteRoutes } from '@/config/routes'
import { getMemberAvatar } from '@/providers/assets/assets.helpers'
import { SentryLogger } from '@/utils/logs'
import { shortenString } from '@/utils/misc'
import { formatNumber } from '@/utils/number'
import { formatDateTime } from '@/utils/time'

import {
DialogText,
Expand Down Expand Up @@ -53,7 +52,7 @@ export const TablePaymentsHistory: FC<TablePaymentsHistoryProps> = ({ data, isLo
const mappedData: TableProps['data'] = useMemo(
() =>
data.map((data) => ({
date: <Date date={data.date} block={data.block} />,
date: <DateTimeBlock date={data.date} />,
type: <Type type={data.type} />,
amount: <TokenAmount tokenAmount={data.amount} />,
sender: <Sender sender={data.sender} />,
Expand Down Expand Up @@ -144,19 +143,6 @@ const Sender = ({ sender }: { sender: PaymentHistory['sender'] }) => {
}
}

const Date = ({ date, block }: { date: Date; block: number }) => {
return (
<>
<Text as="p" variant="t200-strong">
{formatDateTime(date)}
</Text>
<Text as="p" variant="t100" margin={{ top: 1 }} color="colorText">
{formatNumber(block || 0)} block
</Text>
</>
)
}

const Type = ({ type }: { type: PaymentType }) => {
return (
<TypeWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Meta } from '@storybook/react'

import { CrtTransactionsTableProps, CrtTransactionsTable as _CrtTransactionsTable } from './CrtTransactionsTable'

const member = () => ({
address: '5CrLvuj3zAVYNYSUSiScr5gH9sLrcgME4oKjQf4xu1Zj5B7e',
avatarUrls: [`https://api.dicebear.com/6.x/micah/svg?backgroundColor=b6e3f4,c0aede,d1d4f9&seed=${Math.random()}`],
handle: 'doesnotexist',
loading: false,
})

export default {
title: 'crt/CrtTransactionsTable',
component: _CrtTransactionsTable,
args: {
ticker: '$JBC',
transactions: [
{ date: new Date(), member: member(), action: 'bought', price: 98, qty: 50, amount: 4_900 },
{ date: new Date(), member: member(), action: 'sold', price: 100, qty: 2, amount: 200 },
],
},
} as Meta<CrtTransactionsTableProps>

export const CrtTransactionsTable = {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import styled from '@emotion/styled'

import { Table } from '@/components/Table'
import { cVar, sizes } from '@/styles'

export const StyledTable = styled(Table)`
th:nth-child(n + 3) {
justify-content: end;
}
td:nth-child(n + 3) {
align-items: end;
> div {
align-items: end;
}
}
`

export const Badge = styled.div`
background-color: ${cVar('colorBackgroundStrong')};
border-radius: ${sizes(0.5)};
padding: ${sizes(1)} ${sizes(1.5)};
display: flex;
align-items: center;
gap: ${sizes(1)};
`

export const MemberRow = styled.div`
display: flex;
align-items: center;
gap: ${sizes(2.5)};
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import BN from 'bn.js'
import { FC, useMemo } from 'react'

import { SvgActionArrowBottom, SvgActionArrowTop } from '@/assets/icons'
import { Avatar } from '@/components/Avatar'
import { DateTimeBlock } from '@/components/DateTimeBlock'
import { JoyTokenIcon } from '@/components/JoyTokenIcon'
import { NumberFormat } from '@/components/NumberFormat'
import { TableProps } from '@/components/Table'
import { Loader } from '@/components/_loaders/Loader'

import { Badge, MemberRow, StyledTable } from './CrtTransactionsTable.styles'

const COLUMNS: TableProps['columns'] = [
{ Header: 'Date', accessor: 'date' },
{ Header: 'Member', accessor: 'member' },
{ Header: 'Action', accessor: 'action' },
{ Header: 'Price per unit', accessor: 'price' },
{ Header: 'Quantity', accessor: 'qty' },
{ Header: 'Amount', accessor: 'amount' },
]

type CrtTransaction = {
date: Date
member: {
avatarUrls?: string[] | null
avatarLoading?: boolean
hasAvatarUploadFailed?: boolean
handle?: string | null
loading?: boolean
}
action: 'bought' | 'sold'
price: number | BN
qty: number
amount: number | BN
}

export type CrtTransactionsTableProps = { ticker: string; transactions: CrtTransaction[] }
export const CrtTransactionsTable: FC<CrtTransactionsTableProps> = ({ ticker, transactions }) => {
const data = useMemo(
() =>
transactions.map(({ date, member, action, price, qty, amount }) => ({
date: <DateTimeBlock date={date} />,

member: member.loading ? (
<Loader variant="small" />
) : (
<MemberRow>
<Avatar
size={24}
assetUrls={member.avatarUrls}
loading={member.avatarLoading}
hasAvatarUploadFailed={member.hasAvatarUploadFailed}
/>
{member.handle}
</MemberRow>
),

action:
action === 'bought' ? (
<Badge>
<SvgActionArrowTop />
Bought
</Badge>
) : (
<Badge>
<SvgActionArrowBottom />
Sold
</Badge>
),

price: (
<NumberFormat
as="span"
format="full"
icon={<JoyTokenIcon size={16} variant="silver" />}
value={price}
withDenomination
/>
),

qty: <NumberFormat as="span" format="short" value={qty} customTicker={ticker} withToken />,

amount: (
<NumberFormat
as="span"
format="full"
icon={<JoyTokenIcon size={16} variant="silver" />}
value={amount}
withDenomination
/>
),
})),
[transactions, ticker]
)
return <StyledTable title="Market transactions" columns={COLUMNS} data={data} />
}

0 comments on commit da77aa8

Please sign in to comment.