summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/cta/Pay.tsx
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-09-27 13:06:50 -0300
committerSebastian <sebasjm@gmail.com>2021-09-27 13:06:50 -0300
commitb1bf3538e62a3cc22a436cfc5041c07a2c5e32e9 (patch)
tree418d1f85392fd047888749c3dfec6657187b7eb9 /packages/taler-wallet-webextension/src/cta/Pay.tsx
parent8cde98947ba1a6d8c7928578b053786c4e5db17f (diff)
downloadwallet-core-b1bf3538e62a3cc22a436cfc5041c07a2c5e32e9.tar.gz
wallet-core-b1bf3538e62a3cc22a436cfc5041c07a2c5e32e9.tar.bz2
wallet-core-b1bf3538e62a3cc22a436cfc5041c07a2c5e32e9.zip
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.tsx243
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}`
}