From 3a682287deb9afb114f22a157cf867fd920ffb02 Mon Sep 17 00:00:00 2001 From: siandreev Date: Tue, 30 Apr 2024 12:59:00 +0200 Subject: [PATCH] fix: multi send receivers list modal added --- .../uikit/src/components/Notification.tsx | 25 +++- .../MultiSendConfirmNotification.tsx | 137 +++++++++++------- .../MultiSendReceiversNotification.tsx | 119 +++++++++++++++ 3 files changed, 222 insertions(+), 59 deletions(-) create mode 100644 packages/uikit/src/components/desktop/multi-send/MultiSendReceiversNotification.tsx diff --git a/packages/uikit/src/components/Notification.tsx b/packages/uikit/src/components/Notification.tsx index 6526e6f18..523edfa21 100644 --- a/packages/uikit/src/components/Notification.tsx +++ b/packages/uikit/src/components/Notification.tsx @@ -36,9 +36,10 @@ const NotificationContainer = styled(Container)<{ scrollbarWidth: number }>` `} `; -const NotificationWrapper: FC> = ({ +const NotificationWrapper: FC> = ({ children, - entered + entered, + className }) => { const sdk = useAppSdk(); @@ -47,7 +48,11 @@ const NotificationWrapper: FC> = ({ }, [sdk, entered]); return ( - + {children} ); @@ -406,7 +411,17 @@ export const Notification: FC<{ title?: ReactNode; footer?: ReactNode; children: (afterClose: (action?: () => void) => void) => React.ReactNode; -}> = ({ children, isOpen, hideButton, backShadow, handleClose, title, footer }) => { + wrapperClassName?: string; +}> = ({ + children, + isOpen, + hideButton, + backShadow, + handleClose, + title, + footer, + wrapperClassName +}) => { const [entered, setEntered] = useState(false); const [open, setOpen] = useState(false); const { displayType } = useTheme(); @@ -511,7 +526,7 @@ export const Notification: FC<{ > - + diff --git a/packages/uikit/src/components/desktop/multi-send/MultiSendConfirmNotification.tsx b/packages/uikit/src/components/desktop/multi-send/MultiSendConfirmNotification.tsx index 9488fd8e2..11a9c0848 100644 --- a/packages/uikit/src/components/desktop/multi-send/MultiSendConfirmNotification.tsx +++ b/packages/uikit/src/components/desktop/multi-send/MultiSendConfirmNotification.tsx @@ -27,6 +27,8 @@ import { } from '../../../hooks/blockchain/useSendMultiTransfer'; import { useNavigate } from 'react-router-dom'; import { AppRoute } from '../../../libs/routes'; +import { useDisclosure } from '../../../hooks/useDisclosure'; +import { MultiSendReceiversNotification } from './MultiSendReceiversNotification'; const ConfirmWrapper = styled.div` display: flex; @@ -98,6 +100,17 @@ const WalletNameStyled = styled.div` gap: 6px; `; +const RecipientsContainer = styled.div` + display: flex; + flex-direction: column; + text-align: right; +`; + +const ShowAllButton = styled(Body3)` + color: ${p => p.theme.textAccent}; + cursor: pointer; +`; + const FeeContainer = styled.div` display: flex; flex-direction: column; @@ -116,6 +129,11 @@ const MultiSendConfirmContent: FC<{ onClose: () => void; }> = ({ form, asset, listName, onClose }) => { const { t } = useTranslation(); + const { + isOpen: allRowsIsOpen, + onClose: allRowsOnClose, + onOpen: allRowsOnOpen + } = useDisclosure(); const image = useAssetImage(asset); const { data: rate } = useRate( typeof asset.address === 'string' ? asset.address : asset.address.toRawString() @@ -168,64 +186,75 @@ const MultiSendConfirmContent: FC<{ const navigate = useNavigate(); return ( - - {image ? : } - Transfer - {willBeSent} - {willBeSentInFiat} - - - Wallet - {wallet && ( - - - {wallet.name || t('wallet_title')} - - )} - - - Recipients - {form.rows.length} - - - List - {listName} - - - Fee - - {estimateError ? null : estimateLoading || !tonRate ? ( - <> - - - - ) : ( - <> - ≈ {tonFee} - {fiatFee} - + <> + + {image ? : } + Transfer + {willBeSent} + {willBeSentInFiat} + + + Wallet + {wallet && ( + + + {wallet.name || t('wallet_title')} + )} - - - - + + Recipients + + {form.rows.length} wallets + Show all + + + + List + {listName} + + + Fee + + {estimateError ? null : estimateLoading || !tonRate ? ( + <> + + + + ) : ( + <> + ≈ {tonFee} + {fiatFee} + + )} + + + + { + setTimeout(() => { + onClose(); + navigate(AppRoute.activity); + }, 2000); + }} + isLoading={estimateLoading || !rate} + estimationError={!!estimateError} + /> + + { - setTimeout(() => { - onClose(); - navigate(AppRoute.activity); - }, 2000); - }} - isLoading={estimateLoading || !rate} - estimationError={!!estimateError} /> - + ); }; diff --git a/packages/uikit/src/components/desktop/multi-send/MultiSendReceiversNotification.tsx b/packages/uikit/src/components/desktop/multi-send/MultiSendReceiversNotification.tsx new file mode 100644 index 000000000..62c477176 --- /dev/null +++ b/packages/uikit/src/components/desktop/multi-send/MultiSendReceiversNotification.tsx @@ -0,0 +1,119 @@ +import { FC } from 'react'; +import { Notification } from '../../Notification'; +import styled, { createGlobalStyle } from 'styled-components'; +import { Body2 } from '../../Text'; +import { formatAddress } from '@tonkeeper/core/dist/utils/common'; +import { MultiSendFormTokenized } from '../../../hooks/blockchain/useSendMultiTransfer'; +import { formatFiatCurrency, formatter } from '../../../hooks/balance'; +import { useAppContext } from '../../../hooks/appContext'; +import { useRate } from '../../../state/rates'; +import { TonAsset } from '@tonkeeper/core/dist/entries/crypto/asset/ton-asset'; +import { shiftedDecimals } from '@tonkeeper/core/dist/utils/balance'; + +export const MultiSendReceiversNotification: FC<{ + onClose: () => void; + isOpen: boolean; + form: MultiSendFormTokenized; + asset: TonAsset; +}> = ({ onClose, isOpen, form, asset }) => { + const WrapperStyles = createGlobalStyle` + .multi-send-receivers-notification { + max-width: 1000px; + } + `; + + return ( + <> + + + {() => } + + + ); +}; + +const ReceiversTableContainer = styled.div` + display: grid; + grid-template-columns: max-content minmax(88px, 1fr) max-content max-content; + column-gap: 8px; + align-items: center; + grid-auto-rows: 36px 1px; + padding: 0 12px; + background-color: ${p => p.theme.backgroundContent}; + border-radius: ${p => p.theme.corner2xSmall}; +`; + +const RecipientCell = styled(Body2)` + color: ${p => p.theme.textSecondary}; + font-family: ${p => p.theme.fontMono}; +`; + +const CommentCell = styled(Body2)` + overflow: hidden; + text-overflow: ellipsis; +`; + +const FiatCell = styled(Body2)` + color: ${p => p.theme.textSecondary}; + padding-right: 1rem; +`; + +const AmountCell = styled(Body2)` + text-align: right; +`; + +const Divider = styled.div` + background-color: ${p => p.theme.separatorCommon}; + height: 1px; + grid-column: 1/-1; + margin: 0 -1rem; +`; + +const ReceiversTable: FC<{ form: MultiSendFormTokenized; asset: TonAsset }> = ({ form, asset }) => { + const toStringReceiver = (item: MultiSendFormTokenized['rows'][number]['receiver']) => { + if (item && 'dns' in item) { + return item.dns.account.name; + } + + return formatAddress(item!.address); + }; + + const { fiat } = useAppContext(); + const { data: rate } = useRate(asset.address === 'TON' ? 'TON' : asset.address.toRawString()); + + const fiatToString = (weiAmount: MultiSendFormTokenized['rows'][number]['weiAmount']) => { + return formatFiatCurrency( + fiat, + shiftedDecimals(weiAmount, asset.decimals).multipliedBy(rate?.prices || 0) + ); + }; + + const amountToString = (weiAmount: MultiSendFormTokenized['rows'][number]['weiAmount']) => { + return ( + formatter.format(shiftedDecimals(weiAmount, asset.decimals), { + decimals: asset.decimals + }) + + ' ' + + asset.symbol + ); + }; + + return ( + + {form.rows.map((item, index) => ( + <> + {toStringReceiver(item.receiver)} + {item.comment} + ≈ {fiatToString(item.weiAmount)} + {amountToString(item.weiAmount)} + {index !== form.rows.length - 1 && } + + ))} + + ); +};