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

feat: APP-2795 - Implement AssetDataListItemStructure module component #128

Merged
merged 30 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
24c64b8
feat: implment DaoDataListItem
sepehr2github Mar 11, 2024
cc66327
tests added
sepehr2github Mar 12, 2024
b2205c0
add responsive support
sepehr2github Mar 12, 2024
7fc474d
fix: final cleanup
sepehr2github Mar 12, 2024
fbddc6a
chore: update CHANGELOG.MD
sepehr2github Mar 12, 2024
45d5073
Update CHANGELOG.md
sepehr2github Mar 12, 2024
5006ac3
Update src/modules/components/dao/daoDataListItem/index.ts
sepehr2github Mar 12, 2024
55b0102
Update src/modules/components/dao/daoDataListItem/daoDataListItem.tsx
sepehr2github Mar 12, 2024
aafac5e
fix: resolve comment
sepehr2github Mar 12, 2024
5c9e782
Merge branch 'f/app-2789' of https://github.com/aragon/ods into f/app…
sepehr2github Mar 12, 2024
ebf3330
fix: update file names
sepehr2github Mar 12, 2024
0b92344
resolve comments
sepehr2github Mar 13, 2024
eddc477
Merge branch 'main' into f/app-2789
sepehr2github Mar 13, 2024
783084b
fix: update classes
sepehr2github Mar 13, 2024
704482d
Update CHANGELOG.md
sepehr2github Mar 13, 2024
af7c4fb
Update src/modules/components/dao/daoDataListItem/daoDataListItemStru…
sepehr2github Mar 13, 2024
5267ae7
fix: update padding based on figma sizes
sepehr2github Mar 13, 2024
40a84d7
Merge branch 'main' into f/app-2789
sepehr2github Mar 13, 2024
95ef87d
update changelog
sepehr2github Mar 13, 2024
04a5a5a
Merge branch 'main' into f/app-2789
sepehr2github Mar 13, 2024
3b469f8
feature: added AssetDataListItem.Structure
sepehr2github Mar 15, 2024
e7ee172
chore: Merge branch 'main' into f/app-2795
sepehr2github Mar 15, 2024
234f6c1
fix: comments
sepehr2github Mar 15, 2024
fa2df21
Merge branch 'main' into f/app-2795
sepehr2github Mar 18, 2024
10505a5
fix: prettier
sepehr2github Mar 19, 2024
7791714
resolve comments
sepehr2github Mar 26, 2024
c6821e2
chore: merge main branch
sepehr2github Mar 26, 2024
c805883
chore: update tests
sepehr2github Mar 26, 2024
6b41b22
fix: remove logoSrc separator
sepehr2github Mar 26, 2024
4dd40e1
resolve round 2
sepehr2github Mar 27, 2024
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
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Added

- Implement `DaoDataListItem.Structure`, `ProposalDataListItem.Structure`, `MemberDataListItem.Structure` and
`AddressInput` module components
- Implement `DaoDataListItem.Structure`, `ProposalDataListItem.Structure`, `MemberDataListItem.Structure`,
`AssetDataListItem.Structure` and `AddressInput` module components
- Implement `StatePingAnimation` core component
- Implement `addressUtils` and `ensUtils` module utilities
- Implement `useDebouncedValue` core hook and `clipboardUtils` core utility
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { Meta, StoryObj } from '@storybook/react';
import { DataList } from '../../../../../core';
import { AssetDataListItemStructure } from './assetDataListItemStructure';

const meta: Meta<typeof AssetDataListItemStructure> = {
title: 'Modules/Components/Asset/AssetDataListItem/AssetDataListItem.Structure',
component: AssetDataListItemStructure,
tags: ['autodocs'],
parameters: {
design: {
type: 'figma',
url: 'https://www.figma.com/file/P0GeJKqILL7UXvaqu5Jj7V/v1.1.0?type=design&node-id=8079-18352&mode=design&t=MR1awSDoExtPDiEd-4',
},
},
};

type Story = StoryObj<typeof AssetDataListItemStructure>;

/**
* Default usage example of the AssetDataListItem component.
*/
export const Default: Story = {
args: {
logoSrc: 'https://assets.coingecko.com/coins/images/279/standard/ethereum.png?1696501628',
name: 'Ethereum',
amount: 420.69,
symbol: 'ETH',
fiatPrice: 3654.76,
priceChange: 15,
},
render: (props) => (
<DataList.Root entityLabel="Assets">
<DataList.Container>
<AssetDataListItemStructure {...props} />
</DataList.Container>
</DataList.Root>
),
};

/**
* Usage of the AssetDataListItem without changedAmount and changedPercentage.
*/
export const Fallback: Story = {
args: {
name: 'Ethereum',
amount: 420.69,
symbol: 'ETH',
},
render: (props) => (
<DataList.Root entityLabel="Assets">
<DataList.Container>
<AssetDataListItemStructure {...props} />
</DataList.Container>
</DataList.Root>
),
};

export default meta;
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { render, screen } from '@testing-library/react';
import { DataList } from '../../../../../core';
import { AssetDataListItemStructure, type IAssetDataListItemStructureProps } from './assetDataListItemStructure';

describe('<AssetDataListItem.Structure /> component', () => {
const createTestComponent = (props: Partial<IAssetDataListItemStructureProps> = {}) => {
const completeProps: IAssetDataListItemStructureProps = {
name: 'Ethereum',
symbol: 'ETH',
amount: 420.69,
...props,
};

return (
<DataList.Root entityLabel="Assets">
<DataList.Container>
<AssetDataListItemStructure {...completeProps} />
</DataList.Container>
</DataList.Root>
);
};

it('renders tokenName and symbol', () => {
const props = {
name: 'Ethereum',
symbol: 'ETH',
amount: 420.69,
};

render(createTestComponent(props));
expect(screen.getByText(props.name)).toBeInTheDocument();
expect(screen.getByText(props.symbol)).toBeInTheDocument();
});

it('renders amount, fiat price', async () => {
const props = {
name: 'Ethereum',
symbol: 'ETH',
amount: 420.69,
fiatPrice: 3654.76,
};

render(createTestComponent(props));
const USDAmount = await screen.findByText(/1.54/);
expect(USDAmount).toHaveTextContent('$1.54M');
expect(screen.getByText(props.amount)).toBeInTheDocument();
});

it('handles not passing fiat price', () => {
const props = {
name: 'Ethereum',
symbol: 'ETH',
amount: 0,
priceChange: 0,
};

render(createTestComponent(props));
expect(screen.getByText('Unknown')).toBeInTheDocument(); // Assuming Tag component renders '0%' for zero priceChange
});

it('handle not passing priceChange', async () => {
const props = {
name: 'Ethereum',
amount: 420.69,
symbol: 'ETH',
fiatPrice: 3654.76,
};

render(createTestComponent(props));
expect(screen.getByText('0%')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import classNames from 'classnames';
import type React from 'react';
import { useMemo } from 'react';
import { Avatar, DataList, NumberFormat, Tag, formatterUtils, type IDataListItemProps } from '../../../../../core';

export interface IAssetDataListItemStructureProps extends IDataListItemProps {
/**
* The name of the asset.
*/
name: string;
/**
* The symbol of the asset.
*/
symbol: string;
/**
* The amount of the asset.
*/
amount: number | string;
/**
* The logo source of the asset
*/
logoSrc?: string;
/**
* The fiat price of the asset.
*/
fiatPrice?: number | string;
/**
* the price change in percentage of the asset (E.g. in last 24h).
* @default 0
*/
priceChange?: number;
}

export const AssetDataListItemStructure: React.FC<IAssetDataListItemStructureProps> = (props) => {
const { logoSrc, name, amount, symbol, fiatPrice, priceChange = 0, ...otherProps } = props;

const usdAmountChanged = useMemo(() => {
if (!fiatPrice || !priceChange) {
return 0;
}
const usdAmount = (amount ? Number(amount) : 0) * (fiatPrice ? Number(fiatPrice) : 0);
sepehr2github marked this conversation as resolved.
Show resolved Hide resolved
const oldUsdAmount = (100 / (priceChange + 100)) * usdAmount;
return usdAmount - oldUsdAmount;
}, [amount, fiatPrice, priceChange]);

const sign = (value: number) => (value > 0 ? '+' : value < 0 ? '-' : '');
sepehr2github marked this conversation as resolved.
Show resolved Hide resolved

const changedAmountClasses = classNames(
'text-sm font-normal leading-tight md:text-base',
{ 'text-success-800': usdAmountChanged > 0 },
{ 'text-neutral-500': usdAmountChanged === 0 },
{ 'text-critical-800': usdAmountChanged < 0 },
);

const formattedAmount = formatterUtils.formatNumber(amount, {
format: NumberFormat.TOKEN_AMOUNT_SHORT,
fallback: '',
});

const formattedPrice = formatterUtils.formatNumber(
(amount ? Number(amount) : 0) * (fiatPrice ? Number(fiatPrice) : 0),
{
format: NumberFormat.FIAT_TOTAL_SHORT,
fallback: '-',
},
);

const formattedPriceChanged = formatterUtils.formatNumber(Math.abs(usdAmountChanged), {
format: NumberFormat.FIAT_TOTAL_SHORT,
});

const formattedPriceChangedPercentage = formatterUtils.formatNumber(Math.abs(priceChange / 100), {
format: NumberFormat.PERCENTAGE_SHORT,
});

return (
<DataList.Item {...otherProps}>
<div className="flex gap-x-3 py-0 md:py-1.5">
<div className="flex items-center">
<Avatar src={logoSrc} responsiveSize={{ md: 'md', sm: 'sm' }} className="block" />
</div>
<div className=" flex w-full justify-between">
<div className="flex flex-col gap-y-0.5">
<span className="truncate text-sm leading-tight text-neutral-800 md:text-base">{name}</span>
<p className="text-sm leading-tight text-neutral-500 md:text-base">
<span>{`${formattedAmount}`} </span>
<span className="truncate">{symbol}</span>
</p>
</div>
<div className="flex flex-col items-end justify-center gap-y-0.5">
{fiatPrice ? (
<>
<span className="text-sm leading-tight text-neutral-800 md:text-base">
{formattedPrice}
</span>
<div className="flex items-center gap-x-1">
<span className={changedAmountClasses}>
{sign(usdAmountChanged)}
{formattedPriceChanged}
</span>
<Tag
label={`${sign(priceChange / 100)}${formattedPriceChangedPercentage}`}
variant={priceChange > 0 ? 'success' : priceChange < 0 ? 'critical' : 'neutral'}
/>
</div>
</>
) : (
<span className="text-sm leading-tight text-neutral-800 md:text-base">Unknown</span>
)}
</div>
</div>
</div>
</DataList.Item>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AssetDataListItemStructure, type IAssetDataListItemStructureProps } from './assetDataListItemStructure';
7 changes: 7 additions & 0 deletions src/modules/components/asset/assetDataListItem/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { AssetDataListItemStructure } from './assetDataListItemStructure';

export const AssetDataListItem = {
Structure: AssetDataListItemStructure,
};

export type { IAssetDataListItemStructureProps } from './assetDataListItemStructure';
1 change: 1 addition & 0 deletions src/modules/components/asset/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './assetDataListItem';
sepehr2github marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
import { DaoDataListItemStructure } from './daoDataListItemStructure';

export const DaoDataListItem = {
Structure: DaoDataListItemStructure,
};

export type { IDaoDataListItemStructureProps } from './daoDataListItemStructure';
export { DaoDataListItemStructure, type IDaoDataListItemStructureProps } from './daoDataListItemStructure';
8 changes: 7 additions & 1 deletion src/modules/components/dao/daoDataListItem/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export * from './daoDataListItemStructure';
import { DaoDataListItemStructure } from './daoDataListItemStructure';

export const DaoDataListItem = {
Structure: DaoDataListItemStructure,
};

export type { IDaoDataListItemStructureProps } from './daoDataListItemStructure';
1 change: 1 addition & 0 deletions src/modules/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './address';
export * from './asset';
export * from './dao';
export * from './member';
export * from './odsModulesProvider';
Expand Down
8 changes: 7 additions & 1 deletion src/modules/components/member/memberDataListItem/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export * from './memberDataListItemStructure';
import { MemberDataListItemStructure } from './memberDataListItemStructure';

export const MemberDataListItem = {
Structure: MemberDataListItemStructure,
};

export type { IMemberDataListItemProps } from './memberDataListItemStructure';
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
import { MemberDataListItemStructure } from './memberDataListItemStructure';

export const MemberDataListItem = {
Structure: MemberDataListItemStructure,
};

export type { IMemberDataListItemProps } from './memberDataListItemStructure';
export { MemberDataListItemStructure, type IMemberDataListItemProps } from './memberDataListItemStructure';
Loading