diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/components/PendingTransactions.tsx')
-rw-r--r-- | packages/taler-wallet-webextension/src/components/PendingTransactions.tsx | 180 |
1 files changed, 134 insertions, 46 deletions
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx index 5d5dae092..c94010ede 100644 --- a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx +++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx @@ -18,45 +18,63 @@ import { Amounts, NotificationType, Transaction, + TransactionMajorState, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { Fragment, h, JSX, VNode } from "preact"; import { useEffect } from "preact/hooks"; -import { useTranslationContext } from "../context/translation.js"; +import { useBackendContext } from "../context/backend.js"; +import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; import { Avatar } from "../mui/Avatar.js"; +import { Grid } from "../mui/Grid.js"; import { Typography } from "../mui/Typography.js"; -import { wxApi } from "../wxApi.js"; import Banner from "./Banner.js"; import { Time } from "./Time.js"; interface Props extends JSX.HTMLAttributes { - goToTransaction: (id: string) => Promise<void>; + goToTransaction?: (id: string) => Promise<void>; + goToURL: (url: string) => void; } -export function PendingTransactions({ goToTransaction }: Props): VNode { +/** + * this cache will save the tx from the previous render + */ +const cache = { tx: [] as Transaction[] }; + +export function PendingTransactions({ + goToTransaction, + goToURL, +}: Props): VNode { + const api = useBackendContext(); const state = useAsyncAsHook(() => - wxApi.wallet.call(WalletApiOperation.GetTransactions, {}), + api.wallet.call(WalletApiOperation.GetTransactions, {}), ); useEffect(() => { - return wxApi.listener.onUpdateNotification( - [NotificationType.WithdrawGroupFinished], + return api.listener.onUpdateNotification( + [NotificationType.TransactionStateTransition], state?.retry, ); }); const transactions = !state || state.hasError - ? [] - : state.response.transactions.filter((t) => t.pending); + ? cache.tx + : state.response.transactions.filter( + (t) => t.txState.major === TransactionMajorState.Pending, + ); - if (!state || state.hasError || !transactions.length) { + if (state && !state.hasError) { + cache.tx = transactions; + } + if (!transactions.length) { return <Fragment />; } return ( <PendingTransactionsView goToTransaction={goToTransaction} + goToURL={goToURL} transactions={transactions} /> ); @@ -65,52 +83,122 @@ export function PendingTransactions({ goToTransaction }: Props): VNode { export function PendingTransactionsView({ transactions, goToTransaction, + goToURL, }: { - goToTransaction: (id: string) => Promise<void>; + goToTransaction?: (id: string) => Promise<void>; + goToURL: (id: string) => void; transactions: Transaction[]; }): VNode { const { i18n } = useTranslationContext(); + const kycTransaction = transactions.find((tx) => tx.kycUrl); + if (kycTransaction) { + return ( + <div + style={{ + backgroundColor: "#fff3cd", + color: "#664d03", + display: "flex", + justifyContent: "center", + }} + > + <Banner + titleHead={i18n.str`KYC requirement`} + style={{ + backgroundColor: "lightred", + maxHeight: 150, + padding: 8, + flexGrow: 1, //#fff3cd //#ffecb5 + maxWidth: 500, + overflowY: transactions.length > 3 ? "scroll" : "hidden", + }} + > + <Grid + container + item + xs={1} + wrap="nowrap" + role="button" + spacing={1} + alignItems="center" + onClick={() => { + goToURL(kycTransaction.kycUrl ?? "#"); + }} + > + <Grid item> + <Typography inline bold> + One or more transaction require a KYC step to complete + </Typography> + </Grid> + </Grid> + </Banner> + </div> + ); + } + + if (!goToTransaction) return <Fragment />; + return ( - <Banner - titleHead={<i18n.Translate>PENDING OPERATIONS</i18n.Translate>} + <div style={{ backgroundColor: "lightcyan", - maxHeight: 150, - padding: 8, - flexGrow: 1, - maxWidth: 500, - overflowY: transactions.length > 3 ? "scroll" : "hidden", + display: "flex", + justifyContent: "center", }} - elements={transactions.map((t) => { - const amount = Amounts.parseOrThrow(t.amountEffective); - return { - icon: ( - <Avatar - style={{ - border: "solid blue 1px", - color: "blue", - boxSizing: "border-box", + > + <Banner + titleHead={i18n.str`PENDING OPERATIONS`} + style={{ + backgroundColor: "lightcyan", + maxHeight: 150, + padding: 8, + flexGrow: 1, + maxWidth: 500, + overflowY: transactions.length > 3 ? "scroll" : "hidden", + }} + > + {transactions.map((t, i) => { + const amount = Amounts.parseOrThrow(t.amountEffective); + return ( + <Grid + container + item + xs={1} + key={i} + wrap="nowrap" + role="button" + spacing={1} + alignItems="center" + onClick={() => { + goToTransaction(t.transactionId); }} > - {t.type.substring(0, 1)} - </Avatar> - ), - action: () => goToTransaction(t.transactionId), - description: ( - <Fragment> - <Typography inline bold> - {amount.currency} {Amounts.stringifyValue(amount)} - </Typography> - - - <Time - timestamp={AbsoluteTime.fromTimestamp(t.timestamp)} - format="dd MMMM yyyy" - /> - </Fragment> - ), - }; - })} - /> + <Grid item xs={"auto"}> + <Avatar + style={{ + border: "solid blue 1px", + color: "blue", + boxSizing: "border-box", + }} + > + {t.type.substring(0, 1)} + </Avatar> + </Grid> + + <Grid item> + <Typography inline bold> + {amount.currency} {Amounts.stringifyValue(amount)} + </Typography> + - + <Time + timestamp={AbsoluteTime.fromPreciseTimestamp(t.timestamp)} + format="dd MMMM yyyy" + /> + </Grid> + </Grid> + ); + })} + </Banner> + </div> ); } |