diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/wallet/Transaction.tsx')
-rw-r--r-- | packages/taler-wallet-webextension/src/wallet/Transaction.tsx | 226 |
1 files changed, 174 insertions, 52 deletions
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index 1472efb40..02c78320a 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -18,62 +18,80 @@ import { AmountLike, Amounts, i18n, + NotificationType, + parsePaytoUri, Transaction, TransactionType, + WithdrawalType, } from "@gnu-taler/taler-util"; -import { h, VNode } from "preact"; +import { ComponentChildren, Fragment, h, VNode } from "preact"; import { route } from "preact-router"; -import { useEffect, useState } from "preact/hooks"; +import { useState } from "preact/hooks"; import emptyImg from "../../static/img/empty.png"; +import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType"; import { ErrorMessage } from "../components/ErrorMessage"; import { Part } from "../components/Part"; import { Button, ButtonDestructive, ButtonPrimary, + CenteredDialog, + InfoBox, ListOfProducts, + Overlay, RowBorderGray, SmallLightText, - WalletBox, WarningBox, } from "../components/styled"; import { Time } from "../components/Time"; +import { useAsyncAsHook } from "../hooks/useAsyncAsHook"; import { Pages } from "../NavigationBar"; import * as wxApi from "../wxApi"; export function TransactionPage({ tid }: { tid: string }): VNode { - const [transaction, setTransaction] = useState<Transaction | undefined>( - undefined, - ); + async function getTransaction(): Promise<Transaction> { + const res = await wxApi.getTransactions(); + const ts = res.transactions.filter((t) => t.transactionId === tid); + if (ts.length > 1) throw Error("more than one transaction with this id"); + if (ts.length === 1) { + return ts[0]; + } + throw Error("no transaction found"); + } - useEffect(() => { - const fetchData = async (): Promise<void> => { - const res = await wxApi.getTransactions(); - const ts = res.transactions.filter((t) => t.transactionId === tid); - if (ts.length === 1) { - setTransaction(ts[0]); - } else { - route(Pages.history); - } - }; - fetchData(); - }, [tid]); + const state = useAsyncAsHook(getTransaction, [ + NotificationType.WithdrawGroupFinished, + ]); - if (!transaction) { + if (!state) { return ( <div> <i18n.Translate>Loading ...</i18n.Translate> </div> ); } + + if (state.hasError) { + route(Pages.history); + return ( + <div> + <i18n.Translate> + There was an error. Redirecting into the history page + </i18n.Translate> + </div> + ); + } + + function goToHistory(): void { + route(Pages.history); + } + return ( <TransactionView - transaction={transaction} - onDelete={() => wxApi.deleteTransaction(tid).then(() => history.go(-1))} - onRetry={() => wxApi.retryTransaction(tid).then(() => history.go(-1))} - onBack={() => { - route(Pages.history); - }} + transaction={state.response} + onDelete={() => wxApi.deleteTransaction(tid).then(goToHistory)} + onRetry={() => wxApi.retryTransaction(tid).then(goToHistory)} + onBack={goToHistory} /> ); } @@ -91,16 +109,28 @@ export function TransactionView({ onRetry, onBack, }: WalletTransactionProps): VNode { - function TransactionTemplate({ children }: { children: VNode[] }): VNode { + const [confirmBeforeForget, setConfirmBeforeForget] = useState(false); + function doCheckBeforeForget(): void { + if ( + transaction.pending && + transaction.type === TransactionType.Withdrawal + ) { + setConfirmBeforeForget(true); + } else { + onDelete(); + } + } + function TransactionTemplate({ + children, + }: { + children: ComponentChildren; + }): VNode { return ( - <WalletBox> + <Fragment> <section style={{ padding: 8, textAlign: "center" }}> <ErrorMessage title={transaction?.error?.hint} /> {transaction.pending && ( - <WarningBox> - This transaction is not completed - <a href="">more info...</a> - </WarningBox> + <WarningBox>This transaction is not completed</WarningBox> )} </section> <section> @@ -116,12 +146,12 @@ export function TransactionView({ <i18n.Translate>retry</i18n.Translate> </ButtonPrimary> ) : null} - <ButtonDestructive onClick={onDelete}> + <ButtonDestructive onClick={doCheckBeforeForget}> <i18n.Translate> Forget </i18n.Translate> </ButtonDestructive> </div> </footer> - </WalletBox> + </Fragment> ); } @@ -138,27 +168,119 @@ export function TransactionView({ ).amount; return ( <TransactionTemplate> + {confirmBeforeForget ? ( + <Overlay> + <CenteredDialog> + <header>Caution!</header> + <section> + If you have already wired money to the exchange you will loose + the chance to get the coins form it. + </section> + <footer> + <Button onClick={() => setConfirmBeforeForget(false)}> + <i18n.Translate> Cancel </i18n.Translate> + </Button> + + <ButtonDestructive onClick={onDelete}> + <i18n.Translate> Confirm </i18n.Translate> + </ButtonDestructive> + </footer> + </CenteredDialog> + </Overlay> + ) : undefined} <h2>Withdrawal</h2> <Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" /> - <br /> - <Part - big - title="Total withdrawn" - text={amountToString(transaction.amountEffective)} - kind="positive" - /> - <Part - big - title="Chosen amount" - text={amountToString(transaction.amountRaw)} - kind="neutral" - /> - <Part - big - title="Exchange fee" - text={amountToString(fee)} - kind="negative" - /> + {transaction.pending ? ( + transaction.withdrawalDetails.type === + WithdrawalType.ManualTransfer ? ( + <Fragment> + <BankDetailsByPaytoType + amount={amountToString(transaction.amountRaw)} + exchangeBaseUrl={transaction.exchangeBaseUrl} + payto={parsePaytoUri( + transaction.withdrawalDetails.exchangePaytoUris[0], + )} + subject={transaction.withdrawalDetails.reservePub} + /> + <p> + <WarningBox> + Make sure to use the correct subject, otherwise the money will + not arrive in this wallet. + </WarningBox> + </p> + <Part + big + title="Total withdrawn" + text={amountToString(transaction.amountEffective)} + kind="positive" + /> + <Part + big + title="Exchange fee" + text={amountToString(fee)} + kind="negative" + /> + </Fragment> + ) : ( + <Fragment> + {!transaction.withdrawalDetails.confirmed && + transaction.withdrawalDetails.bankConfirmationUrl ? ( + <InfoBox> + The bank is waiting for confirmation. Go to the + <a + href={transaction.withdrawalDetails.bankConfirmationUrl} + target="_blank" + rel="noreferrer" + > + bank site + </a> + </InfoBox> + ) : undefined} + {transaction.withdrawalDetails.confirmed && ( + <InfoBox>Waiting for the coins to arrive</InfoBox> + )} + <Part + big + title="Total withdrawn" + text={amountToString(transaction.amountEffective)} + kind="positive" + /> + <Part + big + title="Chosen amount" + text={amountToString(transaction.amountRaw)} + kind="neutral" + /> + <Part + big + title="Exchange fee" + text={amountToString(fee)} + kind="negative" + /> + </Fragment> + ) + ) : ( + <Fragment> + <Part + big + title="Total withdrawn" + text={amountToString(transaction.amountEffective)} + kind="positive" + /> + <Part + big + title="Chosen amount" + text={amountToString(transaction.amountRaw)} + kind="neutral" + /> + <Part + big + title="Exchange fee" + text={amountToString(fee)} + kind="negative" + /> + </Fragment> + )} <Part title="Exchange" text={new URL(transaction.exchangeBaseUrl).hostname} |