Skip to content

Commit

Permalink
feat: extract notification generic component
Browse files Browse the repository at this point in the history
  • Loading branch information
toniocodo committed Oct 5, 2023
1 parent ed8f878 commit c3786a1
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 173 deletions.
16 changes: 11 additions & 5 deletions libs/oeth/redeem/src/hooks.tsx
Expand Up @@ -6,6 +6,7 @@ import {
usePushActivity,
useUpdateActivity,
} from '@origin/oeth/shared';
import { NotificationSnack } from '@origin/shared/components';
import { contracts, tokens } from '@origin/shared/contracts';
import { usePushNotification, useSlippage } from '@origin/shared/providers';
import { isNilOrEmpty, isUserRejected } from '@origin/shared/utils';
Expand Down Expand Up @@ -106,11 +107,16 @@ export const useHandleRedeem = () => {
if (isUserRejected(error)) {
deleteActivity(activity.id);
pushNotification({
title: intl.formatMessage({ defaultMessage: 'Redeem Cancelled' }),
message: intl.formatMessage({
defaultMessage: 'User rejected operation',
}),
severity: 'info',
content: (
<NotificationSnack
title={intl.formatMessage({
defaultMessage: 'Operation Cancelled',
})}
subtitle={intl.formatMessage({
defaultMessage: 'User rejected operation',
})}
/>
),
});
} else {
updateActivity({
Expand Down
@@ -1,5 +1,5 @@
import { Box, Stack, Typography } from '@mui/material';
import { ActivityIcon, LinkIcon } from '@origin/shared/components';
import { Box, Typography } from '@mui/material';
import { ActivityIcon, NotificationSnack } from '@origin/shared/components';
import { isNilOrEmpty } from '@origin/shared/utils';
import { defineMessage, useIntl } from 'react-intl';
import { formatUnits } from 'viem';
Expand Down Expand Up @@ -39,46 +39,41 @@ export const ApprovalNotification = ({
const intl = useIntl();

return (
<Stack direction="row" justifyContent="space-between" sx={sx}>
<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}>
<NotificationSnack
icon={<ActivityIcon status={status} sx={{ width: 20, height: 20 }} />}
title={intl.formatMessage(title[status])}
href={
isNilOrEmpty(txReceipt?.transactionHash)
? null
: `https://etherscan.io/tx/${txReceipt.transactionHash}`
}
subtitle={
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>
)
}
endIcon={
<Box
component="img"
src={tokenIn.icon}
sx={{ width: 24, height: 24 }}
/>
</Stack>
</Stack>
}
/>
);
};
@@ -1,5 +1,9 @@
import { Box, Stack, Typography } from '@mui/material';
import { ActivityIcon, LinkIcon, Mix } from '@origin/shared/components';
import {
ActivityIcon,
Mix,
NotificationSnack,
} from '@origin/shared/components';
import { isNilOrEmpty } from '@origin/shared/utils';
import { defineMessage, useIntl } from 'react-intl';
import { formatUnits } from 'viem';
Expand All @@ -19,7 +23,7 @@ type RedeemNotificationProps = {
amountOut?: bigint;
txReceipt?: TransactionReceipt;
error?: string;
} & Pick<StackProps, 'sx'>;
} & StackProps;

const title: Record<GlobalActivityStatus, MessageDescriptor> = {
pending: defineMessage({ defaultMessage: 'Redeeming' }),
Expand All @@ -36,69 +40,67 @@ export const RedeemNotification = ({
amountOut,
txReceipt,
error,
sx,
...rest
}: RedeemNotificationProps) => {
const intl = useIntl();

return (
<Stack direction="row" justifyContent="space-between" sx={sx}>
<Stack spacing={1}>
<NotificationSnack
{...rest}
icon={<ActivityIcon status={status} sx={{ width: 20, height: 20 }} />}
title={intl.formatMessage(title[status])}
href={
isNilOrEmpty(txReceipt?.transactionHash)
? null
: `https://etherscan.io/tx/${txReceipt.transactionHash}`
}
subtitle={
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>
)
}
endIcon={
<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}`}
/>
)}
<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 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>
}
/>
);
};
@@ -1,5 +1,5 @@
import { Box, Stack, Typography } from '@mui/material';
import { ActivityIcon, LinkIcon } from '@origin/shared/components';
import { ActivityIcon, NotificationSnack } from '@origin/shared/components';
import { isNilOrEmpty } from '@origin/shared/utils';
import { defineMessage, useIntl } from 'react-intl';
import { formatUnits } from 'viem';
Expand All @@ -19,7 +19,7 @@ type SwapNotificationProps = {
amountOut?: bigint;
txReceipt?: TransactionReceipt;
error?: string;
} & Pick<StackProps, 'sx'>;
} & StackProps;

const title: Record<GlobalActivityStatus, MessageDescriptor> = {
pending: defineMessage({ defaultMessage: 'Swapping' }),
Expand All @@ -36,67 +36,65 @@ export const SwapNotification = ({
amountOut,
txReceipt,
error,
sx,
...rest
}: SwapNotificationProps) => {
const intl = useIntl();

return (
<Stack width={1} direction="row" justifyContent="space-between" sx={sx}>
<Stack spacing={1}>
<NotificationSnack
{...rest}
icon={<ActivityIcon status={status} sx={{ width: 20, height: 20 }} />}
title={intl.formatMessage(title[status])}
href={
isNilOrEmpty(txReceipt?.transactionHash)
? null
: `https://etherscan.io/tx/${txReceipt.transactionHash}`
}
subtitle={
isNilOrEmpty(error) ? (
<Typography color="text.tertiary">
{intl.formatMessage(
{
defaultMessage:
'{amountIn} {symbolIn} for {amountOut} {symbolOut}',
},
{
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 },
),
symbolOut: tokenOut.symbol,
},
)}
</Typography>
) : (
<Typography color="error">{error}</Typography>
)
}
endIcon={
<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}`}
/>
)}
<Box
component="img"
src={tokenIn.icon}
sx={{ width: 24, height: 24 }}
/>
<Box
component="img"
src="images/arrow-right.svg"
sx={{ width: 12, height: 12 }}
/>
<Box
component="img"
src={tokenOut.icon}
sx={{ width: 24, height: 24 }}
/>
</Stack>
<Stack direction="row" alignItems="center">
{isNilOrEmpty(error) ? (
<Typography color="text.tertiary">
{intl.formatMessage(
{
defaultMessage:
'{amountIn} {symbolIn} for {amountOut} {symbolOut}',
},
{
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 },
),
symbolOut: tokenOut.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 }}
/>
<Box
component="img"
src="images/arrow-right.svg"
sx={{ width: 12, height: 12 }}
/>
<Box
component="img"
src={tokenOut.icon}
sx={{ width: 24, height: 24 }}
/>
</Stack>
</Stack>
}
/>
);
};

0 comments on commit c3786a1

Please sign in to comment.