Skip to content

Commit

Permalink
feat: add dedicated notifications, add control hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
toniocodo committed Oct 4, 2023
1 parent 4262de4 commit f4f4180
Show file tree
Hide file tree
Showing 10 changed files with 331 additions and 136 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState } from 'react';

import { IconButton } from '@mui/material';
import { ActivityIcon } from '@origin/shared/components';

import { useGlobalStatus } from '../hooks';
import { ActivityIcon } from './ActivityIcon';
import { ActivityPopover } from './ActivityPopover';

import type { IconButtonProps } from '@mui/material';
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { descend, pipe, prop, sort, take } from 'ramda';
import { useIntl } from 'react-intl';

import { useActivityState } from '../state';
import { ActivityItem } from './ActivityItem';
import { ApprovalNotification } from './ApprovalNotification';
import { RedeemNotification } from './RedeemNotification';
import { SwapNotification } from './SwapNotification';

import type { StackProps } from '@mui/material';

Expand Down Expand Up @@ -69,9 +71,18 @@ export const ActivityPopover = ({
{isNilOrEmpty(sortedActivities) ? (
<EmptyActivity sx={{ px: 3, py: 3 }} />
) : (
sortedActivities.map((a) => (
<ActivityItem key={a.id} activity={a} sx={{ px: 3, py: 2 }} />
))
sortedActivities.map(
(a) =>
({
approval: (
<ApprovalNotification key={a.id} {...a} px={3} py={2} />
),
redeem: (
<RedeemNotification key={a.id} {...a} px={3} py={2} />
),
swap: <SwapNotification key={a.id} {...a} px={3} py={2} />,
})[a.type],
)
)}
</Stack>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Box, Stack, Typography } from '@mui/material';
import { ActivityIcon, LinkIcon } from '@origin/shared/components';
import { isNilOrEmpty } from '@origin/shared/utils';
import { defineMessage, useIntl } from 'react-intl';
import { formatUnits } from 'viem';

import type { StackProps } from '@mui/material';
import type { Token } from '@origin/shared/contracts';
import type { MessageDescriptor } from 'react-intl';
import type { TransactionReceipt } from 'viem';

import type { GlobalActivityStatus } from '../types';

type ApprovalNotificationProps = {
status: GlobalActivityStatus;
tokenIn: Token;
tokenOut: Token;
amountIn?: bigint;
txReceipt?: TransactionReceipt;
error?: string;
} & StackProps;

const title: Record<GlobalActivityStatus, MessageDescriptor> = {
pending: defineMessage({ defaultMessage: 'Approving' }),
success: defineMessage({ defaultMessage: 'Approved' }),
error: defineMessage({ defaultMessage: 'Error while approving' }),
idle: defineMessage({ defaultMessage: 'Approve' }),
};

export const ApprovalNotification = ({
status,
tokenIn,
tokenOut,
amountIn,
txReceipt,
error,
...rest
}: ApprovalNotificationProps) => {
const intl = useIntl();

return (
<Stack {...rest} direction="row" justifyContent="space-between">
<Stack spacing={1}>
<Stack direction="row" alignItems="center" spacing={1}>
<ActivityIcon status={status} sx={{ width: 20, height: 20 }} />
<Typography>{intl.formatMessage(title[status])}</Typography>
{!isNilOrEmpty(txReceipt?.transactionHash) && (
<LinkIcon
size={10}
url={`https://etherscan.io/tx/${txReceipt.transactionHash}`}
/>
)}
</Stack>
<Stack direction="row" alignItems="center">
{isNilOrEmpty(error) ? (
<Typography color="text.tertiary">
{intl.formatMessage(
{
defaultMessage: '{amountIn} {symbolIn}',
},
{
amountIn: intl.formatNumber(
+formatUnits(amountIn, tokenIn.decimals),
{ minimumFractionDigits: 4, maximumFractionDigits: 4 },
),
symbolIn: tokenIn.symbol,
},
)}
</Typography>
) : (
<Typography color="error">{error}</Typography>
)}
</Stack>
</Stack>
<Stack direction="row" alignItems="center" spacing={1}>
<Box
component="img"
src={tokenIn.icon}
sx={{ width: 24, height: 24 }}
/>
</Stack>
</Stack>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Box, Stack, Typography } from '@mui/material';
import { ActivityIcon, LinkIcon, Mix } from '@origin/shared/components';
import { isNilOrEmpty } from '@origin/shared/utils';
import { defineMessage, useIntl } from 'react-intl';
import { formatUnits } from 'viem';

import type { StackProps } from '@mui/material';
import type { Token } from '@origin/shared/contracts';
import type { MessageDescriptor } from 'react-intl';
import type { TransactionReceipt } from 'viem';

import type { GlobalActivityStatus } from '../types';

type RedeemNotificationProps = {
status: GlobalActivityStatus;
tokenIn: Token;
tokenOut: Token;
amountIn?: bigint;
amountOut?: bigint;
txReceipt?: TransactionReceipt;
error?: string;
} & StackProps;

const title: Record<GlobalActivityStatus, MessageDescriptor> = {
pending: defineMessage({ defaultMessage: 'Redeeming' }),
success: defineMessage({ defaultMessage: 'Redeemed' }),
error: defineMessage({ defaultMessage: 'Error while redeeming' }),
idle: defineMessage({ defaultMessage: 'Redeem' }),
};

export const RedeemNotification = ({
status,
tokenIn,
tokenOut,
amountIn,
amountOut,
txReceipt,
error,
...rest
}: RedeemNotificationProps) => {
const intl = useIntl();

return (
<Stack {...rest} direction="row" justifyContent="space-between">
<Stack spacing={1}>
<Stack direction="row" alignItems="center" spacing={1}>
<ActivityIcon status={status} sx={{ width: 20, height: 20 }} />
<Typography>{intl.formatMessage(title[status])}</Typography>
{!isNilOrEmpty(txReceipt?.transactionHash) && (
<LinkIcon
size={10}
url={`https://etherscan.io/tx/${txReceipt.transactionHash}`}
/>
)}
</Stack>
<Stack direction="row" alignItems="center">
{isNilOrEmpty(error) ? (
<Typography color="text.tertiary">
{intl.formatMessage(
{
defaultMessage: '{amountIn} {symbolIn}',
},
{
amountIn: intl.formatNumber(
+formatUnits(amountIn, tokenIn.decimals),
{ minimumFractionDigits: 4, maximumFractionDigits: 4 },
),
symbolIn: tokenIn.symbol,
amountOut: intl.formatNumber(
+formatUnits(amountOut, tokenOut.decimals),
{ minimumFractionDigits: 4, maximumFractionDigits: 4 },
),
},
)}
</Typography>
) : (
<Typography color="error">{error}</Typography>
)}
</Stack>
</Stack>
<Stack direction="row" alignItems="center" spacing={1}>
<Box
component="img"
src={tokenIn.icon}
sx={{ width: 24, height: 24 }}
/>
<Box
component="img"
src="images/arrow-right.svg"
sx={{ width: 12, height: 12 }}
/>
<Mix
imgSrc={[
'/images/currency/weth-icon-small.png',
'/images/currency/reth-icon-small.png',
'/images/currency/steth-icon-small.svg',
'/images/currency/frxeth-icon-small.svg',
]}
size={1.5}
/>
</Stack>
</Stack>
);
};
Loading

0 comments on commit f4f4180

Please sign in to comment.