-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
commit d27d8ea Author: KD <[email protected]> Date: Wed Apr 3 13:21:23 2024 +0200 fix: swap out for additonal span tags commit 2582f01 Author: KD <[email protected]> Date: Wed Apr 3 11:15:09 2024 +0200 fix: remove console.log commit d215d6e Merge: 8e1993e 613663c Author: KD <[email protected]> Date: Wed Apr 3 11:05:38 2024 +0200 Merge branch 'main' of github.com:aragon/ods into feat/APP-2797 commit 8e1993e Author: KD <[email protected]> Date: Wed Apr 3 11:02:28 2024 +0200 fix: resolve PR convos - spy test, move consts, remove unnecessary checks and styles commit b02ab99 Author: KD <[email protected]> Date: Wed Apr 3 10:14:51 2024 +0200 chore: update failed state, revise tests commit 613663c Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Apr 2 12:24:38 2024 +0200 chore: bump express from 4.18.2 to 4.19.2 (#132) commit 6d1979e Author: KD <[email protected]> Date: Mon Apr 1 08:32:10 2024 +0200 fix: TransactionStatus export commit bcce4a4 Merge: cb5edff 1af7dba Author: KD <[email protected]> Date: Sun Mar 31 23:05:35 2024 +0200 chore: resolve merge conflict - update CHANGELOG commit cb5edff Author: KD <[email protected]> Date: Sun Mar 31 23:04:16 2024 +0200 chore: resolve PR conversations - improved readability, block explorer link, new prop naming, etc commit f9c96de Author: KD <[email protected]> Date: Wed Mar 27 19:51:29 2024 +0100 chore: rename effective function commit 680a2b9 Author: KD <[email protected]> Date: Wed Mar 27 19:47:22 2024 +0100 chore: clean up tests commit a8962c0 Author: KD <[email protected]> Date: Wed Mar 27 19:30:59 2024 +0100 feat: implement PR fixes from convos -- logic cleanup, props, index barrelin, etc commit 2d7f6c0 Merge: a18eb16 5ed869c Author: KD <[email protected]> Date: Wed Mar 27 13:30:49 2024 +0100 On feat/APP-2797: pending PR work commit 5ed869c Author: KD <[email protected]> Date: Wed Mar 27 13:30:49 2024 +0100 index on feat/APP-2797: a18eb16 chore: clean up tests commit a18eb16 Author: KD <[email protected]> Date: Tue Mar 26 09:47:16 2024 +0100 chore: clean up tests commit 18c445d Author: KD <[email protected]> Date: Mon Mar 25 17:02:26 2024 +0100 chore: prop cleanup + naming commit b214cff Author: KD <[email protected]> Date: Mon Mar 25 16:37:18 2024 +0100 fix: prevent layout shift with spinner wrapper, extra cleanup commit 64e5894 Author: KD <[email protected]> Date: Mon Mar 25 13:10:54 2024 +0100 fix: update test for unix timestamp to pass on remote CI timezone commit b50ea0c Author: KD <[email protected]> Date: Mon Mar 25 12:17:32 2024 +0100 chore: improve test coverage for failed cases commit e230d1c Merge: 915d27d bd0f4ce Author: KD <[email protected]> Date: Mon Mar 25 11:50:40 2024 +0100 chore: update CHANGELOG commit 915d27d Author: KD <[email protected]> Date: Mon Mar 25 11:40:57 2024 +0100 feat: handle tx status and relationship with tx type commit 57f4eee Author: KD <[email protected]> Date: Thu Mar 21 19:29:29 2024 +0100 chore: update CHANGELOG commit 2919e21 Author: KD <[email protected]> Date: Thu Mar 21 19:28:47 2024 +0100 chore: update index exports commit a358d8e Author: KD <[email protected]> Date: Thu Mar 21 19:28:01 2024 +0100 feat: implement transactionDataListItemStructure component
- Loading branch information
1 parent
1af7dba
commit ece7e60
Showing
10 changed files
with
392 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './transactionDataListItem'; |
10 changes: 10 additions & 0 deletions
10
src/modules/components/transaction/transactionDataListItem/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { TransactionDataListItemStructure as Structure } from './transactionDataListItemStructure/transactionDataListItemStructure'; | ||
|
||
export const TransactionDataListItem = { | ||
Structure, | ||
}; | ||
export { | ||
ITransactionDataListItemProps, | ||
TransactionStatus, | ||
TransactionType, | ||
} from './transactionDataListItemStructure/transactionDataListItemStructure.api'; |
6 changes: 6 additions & 0 deletions
6
.../components/transaction/transactionDataListItem/transactionDataListItemStructure/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export { TransactionDataListItemStructure } from './transactionDataListItemStructure'; | ||
export { | ||
ITransactionDataListItemProps, | ||
TransactionStatus, | ||
TransactionType, | ||
} from './transactionDataListItemStructure.api'; |
104 changes: 104 additions & 0 deletions
104
...transactionDataListItem/transactionDataListItemStructure/transactionDataListItem.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import * as wagmi from 'wagmi'; | ||
import { DataList, NumberFormat, formatterUtils } from '../../../../../core'; | ||
import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; | ||
import { | ||
TransactionStatus, | ||
TransactionType, | ||
type ITransactionDataListItemProps, | ||
} from './transactionDataListItemStructure.api'; | ||
|
||
describe('<TransactionDataListItem.Structure /> component', () => { | ||
const useChainsMock = jest.spyOn(wagmi, 'useChains'); | ||
|
||
beforeEach(() => { | ||
useChainsMock.mockReturnValue([ | ||
{ | ||
id: 1, | ||
blockExplorers: { | ||
default: { name: 'Etherscan', url: 'https://etherscan.io', apiUrl: 'https://api.etherscan.io/api' }, | ||
}, | ||
name: 'Chain Name', | ||
nativeCurrency: { | ||
decimals: 18, | ||
name: 'Ether', | ||
symbol: 'ETH', | ||
}, | ||
rpcUrls: { default: { http: ['https://cloudflare-eth.com'] } }, | ||
}, | ||
]); | ||
}); | ||
|
||
afterEach(() => { | ||
useChainsMock.mockReset(); | ||
}); | ||
|
||
const createTestComponent = (props?: Partial<ITransactionDataListItemProps>) => { | ||
const defaultProps: ITransactionDataListItemProps = { | ||
chainId: 1, | ||
hash: '0x123', | ||
date: '2023-01-01T00:00:00Z', | ||
...props, | ||
}; | ||
return ( | ||
<DataList.Root entityLabel="Daos"> | ||
<DataList.Container> | ||
<TransactionDataListItemStructure {...defaultProps} /> | ||
</DataList.Container> | ||
</DataList.Root> | ||
); | ||
}; | ||
|
||
it('renders the transaction type heading', () => { | ||
const type = TransactionType.ACTION; | ||
render(createTestComponent({ type })); | ||
const transactionTypeHeading = screen.getByText('Smart contract action'); | ||
expect(transactionTypeHeading).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders the token value and symbol in a deposit', () => { | ||
const tokenSymbol = 'ETH'; | ||
const tokenAmount = 10; | ||
const type = TransactionType.DEPOSIT; | ||
render(createTestComponent({ tokenSymbol, tokenAmount, type })); | ||
const tokenPrintout = screen.getByText('10 ETH'); | ||
expect(tokenPrintout).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders the formatted USD estimate', () => { | ||
const tokenPrice = 100; | ||
const tokenAmount = 10; | ||
const type = TransactionType.DEPOSIT; | ||
const formattedEstimate = formatterUtils.formatNumber(tokenPrice * tokenAmount, { | ||
format: NumberFormat.FIAT_TOTAL_SHORT, | ||
}); | ||
render(createTestComponent({ tokenPrice, tokenAmount, type })); | ||
const formattedUsdEstimate = screen.getByText(formattedEstimate as string); | ||
expect(formattedUsdEstimate).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders a failed transaction indicator alongside the transaction type', () => { | ||
render(createTestComponent({ type: TransactionType.DEPOSIT, status: TransactionStatus.FAILED })); | ||
const failedTransactionText = screen.getByText('Deposit'); | ||
expect(failedTransactionText).toBeInTheDocument(); | ||
const closeIcon = screen.getByTestId('CLOSE'); | ||
expect(closeIcon).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders the provided timestamp correctly', () => { | ||
const date = '2000-01-01T00:00:00Z'; | ||
render(createTestComponent({ date })); | ||
expect(screen.getByText(date)).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders with the correct block explorer URL', async () => { | ||
const chainId = 1; | ||
const hash = '0x123'; | ||
render(createTestComponent({ chainId, hash })); | ||
|
||
await waitFor(() => { | ||
const linkElement = screen.getByRole<HTMLAnchorElement>('link'); | ||
expect(linkElement).toHaveAttribute('href', 'https://etherscan.io/tx/0x123'); | ||
}); | ||
}); | ||
}); |
55 changes: 55 additions & 0 deletions
55
...tionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { type Hash } from 'viem'; | ||
import { type IDataListItemProps } from '../../../../../core'; | ||
|
||
export enum TransactionStatus { | ||
PENDING = 'PENDING', | ||
SUCCESS = 'SUCCESS', | ||
FAILED = 'FAILED', | ||
} | ||
|
||
export enum TransactionType { | ||
DEPOSIT = 'DEPOSIT', | ||
WITHDRAW = 'WITHDRAW', | ||
ACTION = 'ACTION', | ||
} | ||
|
||
export interface ITransactionDataListItemProps extends IDataListItemProps { | ||
/** | ||
* The chain ID of the transaction. | ||
*/ | ||
chainId: number; | ||
/** | ||
* The address of the token. | ||
*/ | ||
tokenAddress?: string; | ||
/** | ||
* The symbol of the token, e.g. 'ETH' as a string | ||
*/ | ||
tokenSymbol?: string; | ||
/** | ||
* The token value in the transaction. | ||
*/ | ||
tokenAmount?: number | string; | ||
/** | ||
* The estimated fiat value of the transaction. | ||
*/ | ||
tokenPrice?: number | string; | ||
/** | ||
* The type of transaction. | ||
* @default TransactionType.ACTION | ||
*/ | ||
type?: TransactionType; | ||
/** | ||
* The current status of a blockchain transaction on the network. | ||
* @default TransactionStatus.PENDING | ||
*/ | ||
status?: TransactionStatus; | ||
/** | ||
* The Unix timestamp of the transaction. | ||
*/ | ||
date: string; | ||
/** | ||
* The transaction hash. | ||
*/ | ||
hash: Hash; | ||
} |
71 changes: 71 additions & 0 deletions
71
...ataListItem/transactionDataListItemStructure/transactionDataListItemStructure.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import { DataList } from '../../../../../core'; | ||
import { TransactionDataListItemStructure } from './transactionDataListItemStructure'; | ||
import { TransactionStatus, TransactionType } from './transactionDataListItemStructure.api'; | ||
|
||
const meta: Meta<typeof TransactionDataListItemStructure> = { | ||
title: 'Modules/Components/Transaction/TransactionDataListItem.Structure', | ||
component: TransactionDataListItemStructure, | ||
tags: ['autodocs'], | ||
parameters: { | ||
design: { | ||
type: 'figma', | ||
url: 'https://www.figma.com/file/P0GeJKqILL7UXvaqu5Jj7V/v1.1.0?type=design&node-id=445-5113&mode=design&t=qzF3muTU7z33q8EX-4', | ||
}, | ||
}, | ||
argTypes: { | ||
hash: { | ||
control: 'text', | ||
}, | ||
}, | ||
}; | ||
|
||
type Story = StoryObj<typeof TransactionDataListItemStructure>; | ||
|
||
/** | ||
* Default usage example of the TransactionDataList module component. | ||
*/ | ||
export const Default: Story = { | ||
render: (args) => ( | ||
<DataList.Root entityLabel="Transactions"> | ||
<DataList.Container> | ||
<TransactionDataListItemStructure {...args} /> | ||
</DataList.Container> | ||
</DataList.Root> | ||
), | ||
}; | ||
|
||
export const Withdraw: Story = { | ||
args: { | ||
status: TransactionStatus.SUCCESS, | ||
type: TransactionType.WITHDRAW, | ||
tokenAmount: 10, | ||
tokenSymbol: 'ETH', | ||
}, | ||
render: (args) => ( | ||
<DataList.Root entityLabel="Transactions"> | ||
<DataList.Container> | ||
<TransactionDataListItemStructure {...args} /> | ||
</DataList.Container> | ||
</DataList.Root> | ||
), | ||
}; | ||
|
||
export const Failed: Story = { | ||
args: { | ||
status: TransactionStatus.FAILED, | ||
type: TransactionType.DEPOSIT, | ||
tokenSymbol: 'ETH', | ||
tokenAmount: 10, | ||
tokenPrice: 100, | ||
}, | ||
render: (args) => ( | ||
<DataList.Root entityLabel="Transactions"> | ||
<DataList.Container> | ||
<TransactionDataListItemStructure {...args} /> | ||
</DataList.Container> | ||
</DataList.Root> | ||
), | ||
}; | ||
|
||
export default meta; |
121 changes: 121 additions & 0 deletions
121
...sactionDataListItem/transactionDataListItemStructure/transactionDataListItemStructure.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import classNames from 'classnames'; | ||
import { useChains } from 'wagmi'; | ||
import { | ||
AvatarIcon, | ||
DataList, | ||
IconType, | ||
NumberFormat, | ||
Spinner, | ||
formatterUtils, | ||
type AvatarIconVariant, | ||
} from '../../../../../core'; | ||
import { | ||
TransactionStatus, | ||
TransactionType, | ||
type ITransactionDataListItemProps, | ||
} from './transactionDataListItemStructure.api'; | ||
|
||
const txHeadingStringList: Record<TransactionType, string> = { | ||
[TransactionType.DEPOSIT]: 'Deposit', | ||
[TransactionType.WITHDRAW]: 'Withdraw', | ||
[TransactionType.ACTION]: 'Smart contract action', | ||
}; | ||
|
||
const txIconTypeList: Record<TransactionType, IconType> = { | ||
[TransactionType.DEPOSIT]: IconType.DEPOSIT, | ||
[TransactionType.WITHDRAW]: IconType.WITHDRAW, | ||
[TransactionType.ACTION]: IconType.BLOCKCHAIN_SMARTCONTRACT, | ||
}; | ||
|
||
const txVariantList: Record<TransactionType, AvatarIconVariant> = { | ||
[TransactionType.DEPOSIT]: 'success', | ||
[TransactionType.WITHDRAW]: 'warning', | ||
[TransactionType.ACTION]: 'info', | ||
}; | ||
|
||
export const TransactionDataListItemStructure: React.FC<ITransactionDataListItemProps> = (props) => { | ||
const { | ||
chainId, | ||
tokenAddress, | ||
tokenSymbol, | ||
tokenAmount, | ||
tokenPrice, | ||
type = TransactionType.ACTION, | ||
status = TransactionStatus.PENDING, | ||
// TO-DO: implement formatter decision | ||
date, | ||
hash, | ||
href, | ||
className, | ||
...otherProps | ||
} = props; | ||
const chains = useChains(); | ||
|
||
const matchingChain = chains?.find((chain) => chain.id === chainId); | ||
const blockExplorerBaseUrl = matchingChain?.blockExplorers?.default?.url; | ||
const blockExplorerAssembledHref = blockExplorerBaseUrl ? `${blockExplorerBaseUrl}/tx/${hash}` : undefined; | ||
|
||
const parsedHref = blockExplorerAssembledHref ?? href; | ||
|
||
const formattedTokenValue = formatterUtils.formatNumber(tokenAmount, { | ||
format: NumberFormat.TOKEN_AMOUNT_SHORT, | ||
}); | ||
|
||
const fiatValue = Number(tokenAmount ?? 0) * Number(tokenPrice ?? 0); | ||
const formattedTokenPrice = formatterUtils.formatNumber(fiatValue, { | ||
format: NumberFormat.FIAT_TOTAL_SHORT, | ||
}); | ||
|
||
const formattedTokenAmount = | ||
type === TransactionType.ACTION || tokenAmount == null ? '-' : `${formattedTokenValue} ${tokenSymbol}`; | ||
|
||
return ( | ||
<DataList.Item | ||
className={classNames('px-4 py-0 md:px-6', className)} | ||
href={parsedHref} | ||
target="_blank" | ||
{...otherProps} | ||
> | ||
<div className="flex w-full justify-between py-3 md:py-4"> | ||
<div className="flex items-center gap-x-3 md:gap-x-4"> | ||
{status === TransactionStatus.SUCCESS && ( | ||
<AvatarIcon | ||
className="shrink-0" | ||
variant={txVariantList[type]} | ||
icon={txIconTypeList[type]} | ||
responsiveSize={{ md: 'md' }} | ||
/> | ||
)} | ||
{status === TransactionStatus.FAILED && ( | ||
<AvatarIcon | ||
className="shrink-0" | ||
variant="critical" | ||
icon={IconType.CLOSE} | ||
responsiveSize={{ md: 'md' }} | ||
/> | ||
)} | ||
{status === TransactionStatus.PENDING && ( | ||
<div className="flex size-6 shrink-0 items-center justify-center md:size-8"> | ||
<Spinner className="transition" variant="neutral" responsiveSize={{ md: 'lg' }} /> | ||
</div> | ||
)} | ||
<div className="flex w-full flex-col items-start gap-y-0.5"> | ||
<span className="text-sm font-normal leading-tight text-neutral-800 md:text-base"> | ||
{txHeadingStringList[type]} | ||
</span> | ||
<p className="text-sm font-normal leading-tight text-neutral-500 md:text-base">{date}</p> | ||
</div> | ||
</div> | ||
|
||
<div className="flex flex-col items-end gap-y-0.5"> | ||
<span className="text-sm font-normal leading-tight text-neutral-800 md:text-base"> | ||
{formattedTokenAmount} | ||
</span> | ||
<span className="text-sm font-normal leading-tight text-neutral-500 md:text-base"> | ||
{formattedTokenPrice} | ||
</span> | ||
</div> | ||
</div> | ||
</DataList.Item> | ||
); | ||
}; |
Oops, something went wrong.