diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/wallet/Transaction.tsx')
-rw-r--r-- | packages/taler-wallet-webextension/src/wallet/Transaction.tsx | 855 |
1 files changed, 421 insertions, 434 deletions
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index 10ca67663..1f0293352 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -19,6 +19,7 @@ import { AmountJson, Amounts, AmountString, + DenomLossEventType, MerchantInfo, NotificationType, OrderShortInfo, @@ -230,72 +231,75 @@ function TransactionTemplate({ <Fragment> <section style={{ padding: 8, textAlign: "center" }}> {transaction?.error && - // FIXME: wallet core should stop sending this error on KYC - transaction.error.code !== + // FIXME: wallet core should stop sending this error on KYC + transaction.error.code !== TalerErrorCode.WALLET_WITHDRAWAL_KYC_REQUIRED ? ( <ErrorAlertView error={alertFromError( i18n, - i18n.str`There was an error trying to complete the transaction`, + i18n.str`There was an error trying to complete the transaction.`, transaction.error, )} /> ) : undefined} - {transaction.txState.minor === TransactionMinorState.KycRequired && ( - <AlertView - alert={{ - type: "warning", - message: i18n.str`KYC check required for the transaction to complete`, - description: - transaction.kycUrl && typeof transaction.kycUrl === "string" ? ( - <div> - <i18n.Translate> - Follow this link to the{` `} - <a - rel="noreferrer" - target="_bank" - href={transaction.kycUrl} - > - KYC verifier - </a> - </i18n.Translate> - </div> - ) : ( - i18n.str`No more information has been provided` - ), - }} - /> - )} - {transaction.txState.minor === TransactionMinorState.AmlRequired && ( - <WarningBox> - <i18n.Translate> - The transaction has been blocked since the account required an AML - check - </i18n.Translate> - </WarningBox> - )} - {transaction.txState.major === TransactionMajorState.Pending && ( - <WarningBox> - <div style={{ justifyContent: "center", lineHeight: "25px" }}> - <i18n.Translate>This transaction is not completed</i18n.Translate> - <Link onClick={onRetry} style={{padding: 0}}> - <SvgIcon - title={i18n.str`Retry`} - dangerouslySetInnerHTML={{ __html: refreshIcon }} - color="black" - /> - </Link> - </div> - </WarningBox> - )} + {transaction.txState.major === TransactionMajorState.Pending && + (transaction.txState.minor === TransactionMinorState.KycRequired ? ( + <AlertView + alert={{ + type: "warning", + message: i18n.str`KYC check required for the transaction to complete.`, + description: + transaction.kycUrl && + typeof transaction.kycUrl === "string" ? ( + <div> + <i18n.Translate> + Follow this link to the{` `} + <a + rel="noreferrer" + target="_bank" + href={transaction.kycUrl} + > + KYC verifier. + </a> + </i18n.Translate> + </div> + ) : ( + i18n.str`No additional information has been provided.` + ), + }} + /> + ) : transaction.txState.minor === + TransactionMinorState.AmlRequired ? ( + <WarningBox> + <i18n.Translate> + The transaction has been blocked since the account required an + AML check. + </i18n.Translate> + </WarningBox> + ) : ( + <WarningBox> + <div style={{ justifyContent: "center", lineHeight: "25px" }}> + <i18n.Translate> + This transaction is not completed + </i18n.Translate> + <Link onClick={onRetry} style={{ padding: 0 }}> + <SvgIcon + title={i18n.str`Retry`} + dangerouslySetInnerHTML={{ __html: refreshIcon }} + color="black" + /> + </Link> + </div> + </WarningBox> + ))} {transaction.txState.major === TransactionMajorState.Aborted && ( <InfoBox> - <i18n.Translate>This transaction was aborted</i18n.Translate> + <i18n.Translate>This transaction was aborted.</i18n.Translate> </InfoBox> )} {transaction.txState.major === TransactionMajorState.Failed && ( <ErrorBox> - <i18n.Translate>This transaction failed</i18n.Translate> + <i18n.Translate>This transaction failed.</i18n.Translate> </ErrorBox> )} {confirmBeforeForget ? ( @@ -426,7 +430,7 @@ export function TransactionView({ transaction, onDelete, onAbort, - onBack, + // onBack, onResume, onSuspend, onRetry, @@ -443,10 +447,13 @@ export function TransactionView({ transaction.type === TransactionType.Withdrawal || transaction.type === TransactionType.InternalWithdrawal ) { - const conversion = - transaction.withdrawalDetails.type === WithdrawalType.ManualTransfer - ? transaction.withdrawalDetails.exchangeCreditAccountDetails ?? [] - : []; + // const conversion = + // transaction.withdrawalDetails.type === WithdrawalType.ManualTransfer + // ? transaction.withdrawalDetails.exchangeCreditAccountDetails ?? [] + // : []; + const blockedByKycOrAml = + transaction.txState.minor === TransactionMinorState.KycRequired || + transaction.txState.minor === TransactionMinorState.AmlRequired; return ( <TransactionTemplate transaction={transaction} @@ -466,30 +473,32 @@ export function TransactionView({ {transaction.exchangeBaseUrl} </Header> - {transaction.txState.major !== - TransactionMajorState.Pending ? undefined : transaction.txState - .minor === TransactionMinorState.KycRequired || - transaction.txState.minor === - TransactionMinorState.AmlRequired ? undefined : transaction - .withdrawalDetails.type === WithdrawalType.ManualTransfer - && transaction.withdrawalDetails.exchangeCreditAccountDetails ? ( + {transaction.txState.major !== TransactionMajorState.Pending || + blockedByKycOrAml ? undefined : transaction.withdrawalDetails.type === + WithdrawalType.ManualTransfer && + transaction.withdrawalDetails.exchangeCreditAccountDetails ? ( <Fragment> <InfoBox> - {transaction.withdrawalDetails.exchangeCreditAccountDetails.length > 1 ? + {transaction.withdrawalDetails.exchangeCreditAccountDetails + .length > 1 ? ( <span> <i18n.Translate> - Now the payment service provider is waiting for <Amount value={raw} /> to - be transferred. Select one of the accounts and use the information below - to complete the operation by making a wire transfer from your bank account. + Now the payment service provider is waiting for{" "} + <Amount value={raw} /> to be transferred. Select one of the + accounts and use the information below to complete the + operation by making a wire transfer from your bank account. </i18n.Translate> </span> - : - <span><i18n.Translate> - Now the payment service provider is waiting for <Amount value={raw} /> to - be transferred. Use the information below to complete the operation - by making a wire transfer from your bank account. - </i18n.Translate></span>} - + ) : ( + <span> + <i18n.Translate> + Now the payment service provider is waiting for{" "} + <Amount value={raw} /> to be transferred. Use the + information below to complete the operation by making a wire + transfer from your bank account. + </i18n.Translate> + </span> + )} </InfoBox> <BankDetailsByPaytoType amount={raw} @@ -581,6 +590,7 @@ export function TransactionView({ format="dd MMMM yyyy" /> } + . </i18n.Translate> </td> </tr> @@ -649,11 +659,11 @@ export function TransactionView({ price={getAmountWithFee(effective, raw, "debit")} effectiveRefund={effectiveRefund} info={transaction.info} - proposalId={transaction.proposalId} /> } kind="neutral" /> + <ShowFullContractTermPopup transactionId={transaction.transactionId} /> </TransactionTemplate> ); } @@ -695,7 +705,7 @@ export function TransactionView({ /> {!shouldBeWired ? ( <Part - title={i18n.str`Wire transfer deadline`} + title={i18n.str`Wire transfer deadline.`} text={ <Time timestamp={wireTime} format="dd MMMM yyyy 'at' HH:mm" /> } @@ -705,7 +715,7 @@ export function TransactionView({ <AlertView alert={{ type: "warning", - message: i18n.str`Wire transfer is not initiated`, + message: i18n.str`Wire transfer is not initiated.`, description: i18n.str` `, }} /> @@ -714,7 +724,7 @@ export function TransactionView({ <AlertView alert={{ type: "success", - message: i18n.str`Wire transfer completed`, + message: i18n.str`Wire transfer completed.`, description: i18n.str` `, }} /> @@ -732,7 +742,7 @@ export function TransactionView({ <AlertView alert={{ type: "info", - message: i18n.str`Wire transfer in progress`, + message: i18n.str`Wire transfer in progress.`, description: i18n.str` `, }} /> @@ -1026,10 +1036,110 @@ export function TransactionView({ ); } - if (transaction.type === TransactionType.Recoup) { - throw Error("recoup transaction not implemented"); + if (transaction.type === TransactionType.DenomLoss) { + switch (transaction.lossEventType) { + case DenomLossEventType.DenomExpired: { + return ( + <TransactionTemplate + transaction={transaction} + onDelete={onDelete} + onRetry={onRetry} + onAbort={onAbort} + onResume={onResume} + onSuspend={onSuspend} + onCancel={onCancel} + > + <Header + timestamp={transaction.timestamp} + type={i18n.str`Debit`} + total={effective} + kind="negative" + > + <i18n.Translate>Lost</i18n.Translate> + </Header> + + <Part + title={i18n.str`Exchange`} + text={transaction.exchangeBaseUrl as TranslatedString} + kind="neutral" + /> + <Part + title={i18n.str`Reason`} + text={i18n.str`Denomination expired.`} + /> + </TransactionTemplate> + ); + } + case DenomLossEventType.DenomVanished: { + return ( + <TransactionTemplate + transaction={transaction} + onDelete={onDelete} + onRetry={onRetry} + onAbort={onAbort} + onResume={onResume} + onSuspend={onSuspend} + onCancel={onCancel} + > + <Header + timestamp={transaction.timestamp} + type={i18n.str`Debit`} + total={effective} + kind="negative" + > + <i18n.Translate>Lost</i18n.Translate> + </Header> + + <Part + title={i18n.str`Exchange`} + text={transaction.exchangeBaseUrl as TranslatedString} + kind="neutral" + /> + <Part + title={i18n.str`Reason`} + text={i18n.str`Denomination vanished.`} + /> + </TransactionTemplate> + ); + } + case DenomLossEventType.DenomUnoffered: { + return ( + <TransactionTemplate + transaction={transaction} + onDelete={onDelete} + onRetry={onRetry} + onAbort={onAbort} + onResume={onResume} + onSuspend={onSuspend} + onCancel={onCancel} + > + <Header + timestamp={transaction.timestamp} + type={i18n.str`Debit`} + total={effective} + kind="negative" + > + <i18n.Translate>Lost</i18n.Translate> + </Header> + + <Part + title={i18n.str`Exchange`} + text={transaction.exchangeBaseUrl as TranslatedString} + kind="neutral" + /> + <Part + title={i18n.str`Reason`} + text={i18n.str`Denomination is unoffered.`} + /> + </TransactionTemplate> + ); + } + default: { + assertUnreachable(transaction.lossEventType); + } + } } - if (transaction.type === TransactionType.Reward) { + if (transaction.type === TransactionType.Recoup) { throw Error("recoup transaction not implemented"); } assertUnreachable(transaction); @@ -1075,127 +1185,6 @@ export function MerchantDetails({ ); } -// function DeliveryDetails({ -// date, -// location, -// }: { -// date: TalerProtocolTimestamp | undefined; -// location: Location | undefined; -// }): VNode { -// const { i18n } = useTranslationContext(); -// return ( -// <PurchaseDetailsTable> -// {location && ( -// <Fragment> -// {location.country && ( -// <tr> -// <td> -// <i18n.Translate>Country</i18n.Translate> -// </td> -// <td>{location.country}</td> -// </tr> -// )} -// {location.address_lines && ( -// <tr> -// <td> -// <i18n.Translate>Address lines</i18n.Translate> -// </td> -// <td>{location.address_lines}</td> -// </tr> -// )} -// {location.building_number && ( -// <tr> -// <td> -// <i18n.Translate>Building number</i18n.Translate> -// </td> -// <td>{location.building_number}</td> -// </tr> -// )} -// {location.building_name && ( -// <tr> -// <td> -// <i18n.Translate>Building name</i18n.Translate> -// </td> -// <td>{location.building_name}</td> -// </tr> -// )} -// {location.street && ( -// <tr> -// <td> -// <i18n.Translate>Street</i18n.Translate> -// </td> -// <td>{location.street}</td> -// </tr> -// )} -// {location.post_code && ( -// <tr> -// <td> -// <i18n.Translate>Post code</i18n.Translate> -// </td> -// <td>{location.post_code}</td> -// </tr> -// )} -// {location.town_location && ( -// <tr> -// <td> -// <i18n.Translate>Town location</i18n.Translate> -// </td> -// <td>{location.town_location}</td> -// </tr> -// )} -// {location.town && ( -// <tr> -// <td> -// <i18n.Translate>Town</i18n.Translate> -// </td> -// <td>{location.town}</td> -// </tr> -// )} -// {location.district && ( -// <tr> -// <td> -// <i18n.Translate>District</i18n.Translate> -// </td> -// <td>{location.district}</td> -// </tr> -// )} -// {location.country_subdivision && ( -// <tr> -// <td> -// <i18n.Translate>Country subdivision</i18n.Translate> -// </td> -// <td>{location.country_subdivision}</td> -// </tr> -// )} -// </Fragment> -// )} - -// {!location || !date ? undefined : ( -// <tr> -// <td colSpan={2}> -// <hr /> -// </td> -// </tr> -// )} -// {date && ( -// <Fragment> -// <tr> -// <td> -// <i18n.Translate>Date</i18n.Translate> -// </td> -// <td> -// <Time -// timestamp={AbsoluteTime.fromProtocolTimestamp(date)} -// format="dd MMMM yyyy, HH:mm" -// /> -// </td> -// </tr> -// </Fragment> -// )} -// </PurchaseDetailsTable> -// ); -// } - export function ExchangeDetails({ exchange }: { exchange: string }): VNode { return ( <div> @@ -1255,28 +1244,30 @@ export function InvoiceCreationDetails({ </tr> {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={amount.total} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={amount.total} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1300,28 +1291,30 @@ export function InvoicePaymentDetails({ </tr> {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={amount.value} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={amount.value} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1345,28 +1338,30 @@ export function TransferCreationDetails({ </tr> {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Transfer</i18n.Translate> + </td> + <td> + <Amount value={amount.total} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Transfer</i18n.Translate> - </td> - <td> - <Amount value={amount.total} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1390,31 +1385,34 @@ export function TransferPickupDetails({ </tr> {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={amount.total} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={amount.total} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } + export function WithdrawDetails({ conversion, amount, @@ -1424,12 +1422,6 @@ export function WithdrawDetails({ }): VNode { const { i18n } = useTranslationContext(); - const maxFrac = [amount.fee, amount.fee] - .map((a) => Amounts.maxFractionalDigits(a)) - .reduce((c, p) => Math.max(c, p), 0); - - const total = Amounts.add(amount.value, amount.fee).amount; - return ( <PurchaseDetailsTable> {conversion ? ( @@ -1443,7 +1435,7 @@ export function WithdrawDetails({ </td> </tr> {conversion.fraction === amount.value.fraction && - conversion.value === amount.value.value ? undefined : ( + conversion.value === amount.value.value ? undefined : ( <tr> <td> <i18n.Translate>Converted</i18n.Translate> @@ -1465,28 +1457,30 @@ export function WithdrawDetails({ </tr> )} {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={amount.total} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={amount.total} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1494,27 +1488,16 @@ export function WithdrawDetails({ export function PurchaseDetails({ price, effectiveRefund, - info, - proposalId, + info: _info, }: { price: AmountWithFee; effectiveRefund?: AmountJson; info: OrderShortInfo; - proposalId: string; }): VNode { const { i18n } = useTranslationContext(); const total = Amounts.add(price.value, price.fee).amount; - // const hasProducts = info.products && info.products.length > 0; - - // const hasShipping = - // info.delivery_date !== undefined || info.delivery_location !== undefined; - - const showLargePic = (): void => { - return; - }; - return ( <PurchaseDetailsTable> <tr> @@ -1526,69 +1509,72 @@ export function PurchaseDetails({ </td> </tr> {Amounts.isNonZero(price.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={price.fee} /> - </td> - </tr> - )} - {effectiveRefund && Amounts.isNonZero(effectiveRefund) ? ( - <Fragment> - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Subtotal</i18n.Translate> - </td> - <td> - <Amount value={price.total} /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Refunded</i18n.Translate> - </td> - <td> - <Amount value={effectiveRefund} negative /> - </td> - </tr> - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={Amounts.sub(total, effectiveRefund).amount} /> - </td> - </tr> - </Fragment> - ) : ( <Fragment> <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> <td> - <i18n.Translate>Total</i18n.Translate> + <i18n.Translate>Fees</i18n.Translate> </td> <td> - <Amount value={price.value} /> + <Amount value={price.fee} /> </td> </tr> + {effectiveRefund && Amounts.isNonZero(effectiveRefund) ? ( + <Fragment> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Subtotal</i18n.Translate> + </td> + <td> + <Amount value={price.total} /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Refunded</i18n.Translate> + </td> + <td> + <Amount value={effectiveRefund} negative /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={Amounts.sub(total, effectiveRefund).amount} /> + </td> + </tr> + </Fragment> + ) : ( + <Fragment> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={price.value} /> + </td> + </tr> + </Fragment> + )} </Fragment> )} + {/* {hasProducts && ( <tr> <td colSpan={2}> @@ -1634,11 +1620,6 @@ export function PurchaseDetails({ </td> </tr> )} */} - <tr> - <td> - <ShowFullContractTermPopup proposalId={proposalId} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1658,28 +1639,30 @@ function RefundDetails({ amount }: { amount: AmountWithFee }): VNode { </tr> {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={amount.total} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={amount.total} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1740,7 +1723,7 @@ function TrackingDepositDetails({ </tr> {wireTransfers.map((wire) => ( - <tr> + <tr key={wire.id}> <td>{wire.id}</td> <td> <Amount value={wire.amount} /> @@ -1750,6 +1733,7 @@ function TrackingDepositDetails({ </PurchaseDetailsTable> ); } + function DepositDetails({ amount }: { amount: AmountWithFee }): VNode { const { i18n } = useTranslationContext(); @@ -1765,28 +1749,30 @@ function DepositDetails({ amount }: { amount: AmountWithFee }): VNode { </tr> {Amounts.isNonZero(amount.fee) && ( - <tr> - <td> - <i18n.Translate>Fees</i18n.Translate> - </td> - <td> - <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> - </td> - </tr> + <Fragment> + <tr> + <td> + <i18n.Translate>Fees</i18n.Translate> + </td> + <td> + <Amount value={amount.fee} maxFracSize={amount.maxFrac} /> + </td> + </tr> + <tr> + <td colSpan={2}> + <hr /> + </td> + </tr> + <tr> + <td> + <i18n.Translate>Total</i18n.Translate> + </td> + <td> + <Amount value={amount.total} maxFracSize={amount.maxFrac} /> + </td> + </tr> + </Fragment> )} - <tr> - <td colSpan={2}> - <hr /> - </td> - </tr> - <tr> - <td> - <i18n.Translate>Total</i18n.Translate> - </td> - <td> - <Amount value={amount.total} maxFracSize={amount.maxFrac} /> - </td> - </tr> </PurchaseDetailsTable> ); } @@ -1976,8 +1962,9 @@ function ShowWithdrawalDetailForBankIntegrated({ if ( transaction.txState.major !== TransactionMajorState.Pending || transaction.withdrawalDetails.type === WithdrawalType.ManualTransfer - ) + ) { return <Fragment />; + } const raw = Amounts.parseOrThrow(transaction.amountRaw); return ( <Fragment> @@ -1989,7 +1976,7 @@ function ShowWithdrawalDetailForBankIntegrated({ setShowDetails(!showDetails); }} > - show details + Show details. </a> </EnabledBySettings> @@ -2003,7 +1990,7 @@ function ShowWithdrawalDetailForBankIntegrated({ /> )} {!transaction.withdrawalDetails.confirmed && - transaction.withdrawalDetails.bankConfirmationUrl ? ( + transaction.withdrawalDetails.bankConfirmationUrl ? ( <InfoBox> <div style={{ display: "block" }}> <i18n.Translate> @@ -2026,7 +2013,7 @@ function ShowWithdrawalDetailForBankIntegrated({ <InfoBox> <i18n.Translate> Bank has confirmed the wire transfer. Waiting for the exchange to - send the coins + send the coins. </i18n.Translate> </InfoBox> )} |