diff options
author | Sebastian <sebasjm@gmail.com> | 2021-09-27 13:06:50 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-09-27 13:06:50 -0300 |
commit | b1bf3538e62a3cc22a436cfc5041c07a2c5e32e9 (patch) | |
tree | 418d1f85392fd047888749c3dfec6657187b7eb9 /packages/taler-wallet-webextension/src/cta/Pay.tsx | |
parent | 8cde98947ba1a6d8c7928578b053786c4e5db17f (diff) | |
download | wallet-core-b1bf3538e62a3cc22a436cfc5041c07a2c5e32e9.tar.xz |
some ui fixing from belen comments
Diffstat (limited to 'packages/taler-wallet-webextension/src/cta/Pay.tsx')
-rw-r--r-- | packages/taler-wallet-webextension/src/cta/Pay.tsx | 243 |
1 files changed, 133 insertions, 110 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx b/packages/taler-wallet-webextension/src/cta/Pay.tsx index c0038f8fd..e7a3415ac 100644 --- a/packages/taler-wallet-webextension/src/cta/Pay.tsx +++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx @@ -24,56 +24,45 @@ */ // import * as i18n from "../i18n"; -import { renderAmount, ProgressButton } from "../renderHtml"; -import * as wxApi from "../wxApi"; - -import { useState, useEffect } from "preact/hooks"; - -import { AmountLike, ConfirmPayResultDone, getJsonI18n, i18n } from "@gnu-taler/taler-util"; -import { - PreparePayResult, - ConfirmPayResult, - AmountJson, - PreparePayResultType, - Amounts, - ContractTerms, - ConfirmPayResultType, -} from "@gnu-taler/taler-util"; -import { JSX, VNode, h, Fragment } from "preact"; -import { ButtonDestructive, ButtonSuccess, ButtonWarning, LinkSuccess, LinkWarning, WalletAction } from "../components/styled"; +import { AmountJson, AmountLike, Amounts, ConfirmPayResult, ConfirmPayResultDone, ConfirmPayResultType, ContractTerms, getJsonI18n, i18n, PreparePayResult, PreparePayResultType } from "@gnu-taler/taler-util"; +import { Fragment, JSX, VNode } from "preact"; +import { useEffect, useState } from "preact/hooks"; import { LogoHeader } from "../components/LogoHeader"; import { Part } from "../components/Part"; import { QR } from "../components/QR"; +import { ButtonSuccess, LinkSuccess, SuccessBox, WalletAction, WarningBox } from "../components/styled"; +import { useBalances } from "../hooks/useBalances"; +import * as wxApi from "../wxApi"; interface Props { talerPayUri?: string } -export function AlreadyPaid({ payStatus }: { payStatus: PreparePayResult }) { - const fulfillmentUrl = payStatus.contractTerms.fulfillment_url; - let message; - if (fulfillmentUrl) { - message = ( - <span> - You have already paid for this article. Click{" "} - <a href={fulfillmentUrl} target="_bank" rel="external">here</a> to view it again. - </span> - ); - } else { - message = <span> - You have already paid for this article:{" "} - <em> - {payStatus.contractTerms.fulfillment_message ?? "no message given"} - </em> - </span>; - } - return <section class="main"> - <h1>GNU Taler Wallet</h1> - <article class="fade"> - {message} - </article> - </section> -} +// export function AlreadyPaid({ payStatus }: { payStatus: PreparePayResult }) { +// const fulfillmentUrl = payStatus.contractTerms.fulfillment_url; +// let message; +// if (fulfillmentUrl) { +// message = ( +// <span> +// You have already paid for this article. Click{" "} +// <a href={fulfillmentUrl} target="_bank" rel="external">here</a> to view it again. +// </span> +// ); +// } else { +// message = <span> +// You have already paid for this article:{" "} +// <em> +// {payStatus.contractTerms.fulfillment_message ?? "no message given"} +// </em> +// </span>; +// } +// return <section class="main"> +// <h1>GNU Taler Wallet</h1> +// <article class="fade"> +// {message} +// </article> +// </section> +// } const doPayment = async (payStatus: PreparePayResult): Promise<ConfirmPayResultDone> => { if (payStatus.status !== "payment-possible") { @@ -98,6 +87,12 @@ export function PayPage({ talerPayUri }: Props): JSX.Element { const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined); const [payErrMsg, setPayErrMsg] = useState<string | undefined>(""); + const balance = useBalances() + const balanceWithoutError = balance?.error ? [] : (balance?.response.balances || []) + + const foundBalance = balanceWithoutError.find(b => payStatus && Amounts.parseOrThrow(b.available).currency === Amounts.parseOrThrow(payStatus?.amountRaw).currency) + const foundAmount = foundBalance ? Amounts.parseOrThrow(foundBalance.available) : undefined + useEffect(() => { if (!talerPayUri) return; const doFetch = async (): Promise<void> => { @@ -115,24 +110,24 @@ export function PayPage({ talerPayUri }: Props): JSX.Element { return <span>Loading payment information ...</span>; } - if (payResult && payResult.type === ConfirmPayResultType.Done) { - if (payResult.contractTerms.fulfillment_message) { - const obj = { - fulfillment_message: payResult.contractTerms.fulfillment_message, - fulfillment_message_i18n: - payResult.contractTerms.fulfillment_message_i18n, - }; - const msg = getJsonI18n(obj, "fulfillment_message"); - return ( - <div> - <p>Payment succeeded.</p> - <p>{msg}</p> - </div> - ); - } else { - return <span>Redirecting ...</span>; - } - } + // if (payResult && payResult.type === ConfirmPayResultType.Done) { + // if (payResult.contractTerms.fulfillment_message) { + // const obj = { + // fulfillment_message: payResult.contractTerms.fulfillment_message, + // fulfillment_message_i18n: + // payResult.contractTerms.fulfillment_message_i18n, + // }; + // const msg = getJsonI18n(obj, "fulfillment_message"); + // return ( + // <div> + // <p>Payment succeeded.</p> + // <p>{msg}</p> + // </div> + // ); + // } else { + // return <span>Redirecting ...</span>; + // } + // } const onClick = async () => { try { @@ -147,7 +142,7 @@ export function PayPage({ talerPayUri }: Props): JSX.Element { } - return <PaymentRequestView uri={talerPayUri} payStatus={payStatus} onClick={onClick} payErrMsg={payErrMsg} />; + return <PaymentRequestView uri={talerPayUri} payStatus={payStatus} onClick={onClick} payErrMsg={payErrMsg} balance={foundAmount} />; } export interface PaymentRequestViewProps { @@ -155,8 +150,9 @@ export interface PaymentRequestViewProps { onClick: () => void; payErrMsg?: string; uri: string; + balance: AmountJson | undefined; } -export function PaymentRequestView({ uri, payStatus, onClick, payErrMsg }: PaymentRequestViewProps) { +export function PaymentRequestView({ uri, payStatus, onClick, payErrMsg, balance }: PaymentRequestViewProps) { let totalFees: AmountJson = Amounts.getZero(payStatus.amountRaw); const contractTerms: ContractTerms = payStatus.contractTerms; @@ -183,71 +179,98 @@ export function PaymentRequestView({ uri, payStatus, onClick, payErrMsg }: Payme merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>; } - const [showQR, setShowQR] = useState<boolean>(false) - const privateUri = payStatus.status !== PreparePayResultType.AlreadyConfirmed ? `${uri}&n=${payStatus.noncePriv}` : uri + function Alternative() { + const [showQR, setShowQR] = useState<boolean>(false) + const privateUri = payStatus.status !== PreparePayResultType.AlreadyConfirmed ? `${uri}&n=${payStatus.noncePriv}` : uri + return <section> + <LinkSuccess upperCased onClick={() => setShowQR(qr => !qr)}> + {!showQR ? i18n.str`Pay with a mobile phone` : i18n.str`Hide QR`} + </LinkSuccess> + {showQR && <div> + <QR text={privateUri} /> + Scan the QR code or <a href={privateUri}>click here</a> + </div>} + </section> + } + + function ButtonsSection() { + if (payErrMsg) { + return <section> + <div> + <p>Payment failed: {payErrMsg}</p> + <button class="pure-button button-success" onClick={onClick} > + {i18n.str`Retry`} + </button> + </div> + </section> + } + if (payStatus.status === PreparePayResultType.PaymentPossible) { + return <Fragment> + <section> + <ButtonSuccess upperCased> + {i18n.str`Pay`} {amountToString(payStatus.amountEffective)} + </ButtonSuccess> + </section> + <Alternative /> + </Fragment> + } + if (payStatus.status === PreparePayResultType.InsufficientBalance) { + return <Fragment> + <section> + {balance ? <WarningBox> + Your balance of {amountToString(balance)} is not enough to pay for this purchase + </WarningBox> : <WarningBox> + Your balance is not enough to pay for this purchase. + </WarningBox>} + </section> + <section> + <ButtonSuccess upperCased> + {i18n.str`Withdraw digital cash`} + </ButtonSuccess> + </section> + <Alternative /> + </Fragment> + } + if (payStatus.status === PreparePayResultType.AlreadyConfirmed) { + return <Fragment> + <section> + {payStatus.paid && contractTerms.fulfillment_message && <Part title="Merchant message" text={contractTerms.fulfillment_message} kind='neutral' />} + </section> + {!payStatus.paid && <Alternative />} + </Fragment> + } + return <span /> + } + return <WalletAction> <LogoHeader /> + <h2> {i18n.str`Digital cash payment`} </h2> + {payStatus.status === PreparePayResultType.AlreadyConfirmed && + (payStatus.paid ? <SuccessBox> Already paid </SuccessBox> : <WarningBox> Already confirmed </WarningBox>) + } <section> - {payStatus.status === PreparePayResultType.InsufficientBalance ? - <Part title="Insufficient balance" text="No enough coins to pay" kind='negative' /> : - <Part big title="Total amount with fee" text={amountToString(payStatus.amountEffective)} kind='negative' /> + {payStatus.status !== PreparePayResultType.InsufficientBalance && Amounts.isNonZero(totalFees) && + <Part big title="Total to pay" text={amountToString(payStatus.amountEffective)} kind='negative' /> } <Part big title="Purchase amount" text={amountToString(payStatus.amountRaw)} kind='neutral' /> - {Amounts.isNonZero(totalFees) && <Part big title="Fee" text={amountToString(totalFees)} kind='negative' />} + {Amounts.isNonZero(totalFees) && <Fragment> + <Part big title="Fee" text={amountToString(totalFees)} kind='negative' /> + </Fragment> + } <Part title="Merchant" text={contractTerms.merchant.name} kind='neutral' /> <Part title="Purchase" text={contractTerms.summary} kind='neutral' /> {contractTerms.order_id && <Part title="Receipt" text={`#${contractTerms.order_id}`} kind='neutral' />} </section> - {showQR && <section> - <QR text={privateUri} /> - Scan the QR code or <a href={privateUri}>click here</a> - </section>} - <section> - {payErrMsg ? ( - <div> - <p>Payment failed: {payErrMsg}</p> - <button class="pure-button button-success" onClick={onClick} > - {i18n.str`Retry`} - </button> - </div> - ) : ( - payStatus.status === PreparePayResultType.PaymentPossible ? <Fragment> - <LinkSuccess upperCased onClick={() => setShowQR(qr => !qr)}> - {!showQR ? i18n.str`Complete with mobile wallet` : i18n.str`Hide QR`} - </LinkSuccess> - <ButtonSuccess upperCased> - {i18n.str`Confirm payment`} - </ButtonSuccess> - </Fragment> : ( - payStatus.status === PreparePayResultType.InsufficientBalance ? <Fragment> - <LinkSuccess upperCased onClick={() => setShowQR(qr => !qr)}> - {!showQR ? i18n.str`Pay with other device` : i18n.str`Hide QR`} - </LinkSuccess> - <ButtonDestructive upperCased disabled> - {i18n.str`No enough coins`} - </ButtonDestructive> - </Fragment> : - <Fragment> - {payStatus.contractTerms.fulfillment_message && <div> - {payStatus.contractTerms.fulfillment_message} - </div>} - <LinkWarning upperCased href={payStatus.contractTerms.fulfillment_url}> - {i18n.str`Already paid`} - </LinkWarning> - </Fragment> - - ) - )} + <ButtonsSection /> - </section> </WalletAction> } function amountToString(text: AmountLike) { const aj = Amounts.jsonifyAmount(text) - const amount = Amounts.stringifyValue(aj) + const amount = Amounts.stringifyValue(aj, 2) return `${amount} ${aj.currency}` } |