Skip to content

Commit

Permalink
frontend: revamp send confirm dialog / view
Browse files Browse the repository at this point in the history
Using `View fullscreen` instead of WaitDialog for bb02
and UI improvement in general in order to improve UX
(easier to read).
  • Loading branch information
shonsirsha committed Aug 26, 2024
1 parent 4b318b8 commit d3c6c7c
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 60 deletions.
2 changes: 2 additions & 0 deletions frontends/web/src/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -1533,8 +1533,10 @@
"title": "Send from output"
},
"confirm": {
"infoMessage": "Carefully verify the amount and address are correct on the BitBox02",
"selected-coins": "Selected coins",
"title": "Confirm and send transaction",
"to": "To",
"total": "Total"
},
"error": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
.bitBoxContainer {
margin-bottom: var(--space-half);
}

.bitBoxContainer img {
max-width: 220px;
}

.confirmationItemWrapper {
align-items: baseline;
display: flex;
justify-content: space-between;
}

.confirmItem {
margin-bottom: calc(var(--space-half) + var(--space-quarter));
}

.confirmItem p {
margin: 0;
word-break: break-all;
}

.confirmItem ul {
list-style-type: square;
margin: 0;
margin-top: var(--space-quarter);
padding-left: var(--space-half);
}

.fiatValue {
color: var(--color-secondary);
font-size: 16px;
}

label {
color: var(--color-secondary);
margin: 0 !important;
}

.title {
text-align: center;
}

.totalWrapper {
align-items: baseline;
display: flex;
}

.totalWrapper .fiatValue {
margin-left: auto;
}

.totalWrapper label {
margin-right: var(--space-quarter) !important;
}

.valueOriginal {
font-size: 16px;
font-weight: 500;
}

.valueOriginalLarge {
font-size: var(--header-default-font-size);
font-weight: 500;
}

@media (max-width: 768px) {
.bitBoxContainer img {
padding-right: 16px;
max-width: 190px;
}

.bitBoxContainer svg {
max-width: 16px;
}

label {
font-size: 16px !important;
}

.fiatValue,
.valueOriginal {
font-size: 14px;
}
}
225 changes: 225 additions & 0 deletions frontends/web/src/routes/account/send/components/confirm/confirm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/**
* Copyright 2024 Shift Crypto AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { useTranslation } from 'react-i18next';
import { ConversionUnit } from '@/api/account';
import { Amount } from '@/components/amount/amount';
import { customFeeUnit } from '@/routes/account/utils';
import { View, ViewContent, ViewHeader } from '@/components/view/view';
import { Message } from '@/components/message/message';
import { PointToBitBox02 } from '@/components/icon';
import { TConfirmSendProps } from '@/routes/account/send/components/confirm/types';
import { ConfirmingWaitDialog } from '@/routes/account/send/components/confirm/dialogs/confirm-wait-dialog';
import style from './confirm.module.css';

type TFiatValueProps = {
baseCurrencyUnit: ConversionUnit;
amount: string
}

export const ConfirmSend = (props: TConfirmSendProps) => {
const { device, ...bb01Props } = props;
const { paired, ...bb02Props } = bb01Props;

switch (props.device) {
case 'bitbox':
return (
<ConfirmingWaitDialog
{...bb01Props}
/>
);
case 'bitbox02':
return (
<BB02ConfirmSend
{...bb02Props}
/>
);
default:
return null;
}
};

export const BB02ConfirmSend = ({
baseCurrencyUnit,
note,
hasSelectedUTXOs,
selectedUTXOs,
coinCode,
transactionStatus,
transactionDetails
}: Omit<TConfirmSendProps, 'device' | 'paired'>) => {

const { t } = useTranslation();
const { isConfirming, signProgress } = transactionStatus;
const {
proposedFee,
proposedAmount,
proposedTotal,
customFee,
feeTarget,
recipientAddress,
fiatUnit
} = transactionDetails;


const confirmPrequel = (signProgress && signProgress.steps > 0) ? (
<div className="m-top-none m-bottom-half">
<span>
{
t('send.signprogress.description', {
steps: signProgress.steps.toString(),
})
}
<br />
{t('send.signprogress.label')}: {signProgress.step}/{signProgress.steps}
</span>
</div>
) : undefined;


if (!isConfirming) {
return null;
}

const canShowSendAmountFiatValue = proposedAmount && proposedAmount.conversions && proposedAmount.conversions[fiatUnit];
const canShowFeeFiatValue = proposedFee && proposedFee.conversions && proposedFee.conversions[fiatUnit];
const canShowTotalFiatValue = (proposedTotal && proposedTotal.conversions) && proposedTotal.conversions[fiatUnit];


return (
<View fullscreen>
<ViewHeader title={<div className={style.title}>{t('send.confirm.title')}</div>} />
<ViewContent>
{confirmPrequel}
<Message type="info">
{t('send.confirm.infoMessage')}
</Message>
<div className={style.bitBoxContainer}>
<PointToBitBox02 />
</div>

{/*Send amount*/}
<div className={style.confirmItem}>
<label>{t('button.send')}</label>
<div className={style.confirmationItemWrapper}>
<p className={style.valueOriginalLarge}>
{(proposedAmount &&
<Amount alwaysShowAmounts amount={proposedAmount.amount} unit={proposedAmount.unit}/>) || 'N/A'}
{' '}
<small>{(proposedAmount && proposedAmount.unit) || 'N/A'}</small>
</p>
{canShowSendAmountFiatValue &&
(<FiatValue baseCurrencyUnit={baseCurrencyUnit} amount={proposedAmount.conversions![fiatUnit] || ''} />)
}
</div>
</div>

{/*To (recipient address)*/}
<div className={style.confirmItem}>
<label>{t('send.confirm.to')}</label>
<div className={style.confirmationItemWrapper}>
<p className={`${style.valueOriginal}`}>
{recipientAddress || 'N/A'}
</p>
</div>
</div>

{/*Note*/}
{note ? (
<div className={style.confirmItem}>
<label>{t('note.title')}</label>
<p className={style.valueOriginal}>{note}</p>
</div>
) : null}

{/*Selected UTXOs*/}
{
hasSelectedUTXOs && (
<div className={style.confirmItem}>
<label>{t('send.confirm.selected-coins')}</label>
<ul>
{
selectedUTXOs.map((uxto, i) => (
<li className={style.valueOriginal} key={`selectedCoin-${i}`}>{uxto}</li>
))
}

</ul>

</div>
)
}


{/*Fee*/}
<div className={style.confirmItem}>
<label>{t('send.fee.label')}{feeTarget ? ' (' + t(`send.feeTarget.label.${feeTarget}`) + ')' : ''}</label>
<div className={style.confirmationItemWrapper}>
<p className={style.valueOriginal}>
{(proposedFee &&
<Amount alwaysShowAmounts amount={proposedFee.amount} unit={proposedFee.unit}/>) || 'N/A'}
{' '}
{(proposedFee && proposedFee.unit) || 'N/A'}
{customFee ? (
<span>
<br/>
<small>({customFee} {customFeeUnit(coinCode)})</small>
</span>
) : null}
</p>
{canShowFeeFiatValue &&
(<FiatValue baseCurrencyUnit={baseCurrencyUnit} amount={proposedFee.conversions![fiatUnit] || ''} />)
}

</div>
</div>

{/*Total*/}
<div className={style.confirmItem}>
<div className={style.totalWrapper}>
<label>{t('send.confirm.total')}</label>
<p className={style.valueOriginal}>
<strong>
{(proposedTotal &&
<Amount alwaysShowAmounts amount={proposedTotal.amount} unit={proposedTotal.unit}/>) || 'N/A'}
</strong>
{' '}
<small>{(proposedTotal && proposedTotal.unit) || 'N/A'}</small>
</p>
{canShowTotalFiatValue &&
(<FiatValue baseCurrencyUnit={baseCurrencyUnit} amount={proposedTotal.conversions![fiatUnit] || ''} />)
}
</div>
</div>

</ViewContent>
</View>
);

};


const FiatValue = ({ baseCurrencyUnit, amount }: TFiatValueProps) => {
return (
<p className={style.fiatValue}>
<span>
<Amount alwaysShowAmounts amount={amount} unit={baseCurrencyUnit} />
{' '}<small>{baseCurrencyUnit}</small>
</span>
</p>
)
;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.confirmItem p {
margin-top: var(--space-quarter);
word-break: break-all;
}

.confirmationValue {
font-size: var(--size-default);
font-weight: 400;
line-height: 1;
overflow: hidden;
text-overflow: ellipsis;
direction: rtl;
}

.total p {
font-size: var(--size-subheader) !important;
margin-bottom: var(--space-quarter);
}
Loading

0 comments on commit d3c6c7c

Please sign in to comment.