[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] branch master updated: some ui fixing from belen com
From: |
gnunet |
Subject: |
[taler-wallet-core] branch master updated: some ui fixing from belen comments |
Date: |
Mon, 27 Sep 2021 18:07:00 +0200 |
This is an automated email from the git hooks/post-receive script.
sebasjm pushed a commit to branch master
in repository wallet-core.
The following commit(s) were added to refs/heads/master by this push:
new b1bf3538 some ui fixing from belen comments
b1bf3538 is described below
commit b1bf3538e62a3cc22a436cfc5041c07a2c5e32e9
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Mon Sep 27 13:06:50 2021 -0300
some ui fixing from belen comments
---
packages/taler-util/src/amounts.ts | 4 +-
.../src/components/ErrorMessage.tsx | 2 +-
.../src/components/styled/index.tsx | 16 +-
.../src/cta/Pay.stories.tsx | 62 +++++-
packages/taler-wallet-webextension/src/cta/Pay.tsx | 243 +++++++++++----------
.../src/hooks/useBalances.tsx | 1 -
6 files changed, 211 insertions(+), 117 deletions(-)
diff --git a/packages/taler-util/src/amounts.ts
b/packages/taler-util/src/amounts.ts
index f0434be0..5a8c7f06 100644
--- a/packages/taler-util/src/amounts.ts
+++ b/packages/taler-util/src/amounts.ts
@@ -407,7 +407,7 @@ export class Amounts {
return `${a.currency}:${s}`;
}
- static stringifyValue(a: AmountJson): string {
+ static stringifyValue(a: AmountJson, minFractional: number = 0): string {
const av = a.value + Math.floor(a.fraction / amountFractionalBase);
const af = a.fraction % amountFractionalBase;
let s = av.toString();
@@ -416,7 +416,7 @@ export class Amounts {
s = s + ".";
let n = af;
for (let i = 0; i < amountFractionalLength; i++) {
- if (!n) {
+ if (!n && i >= minFractional) {
break;
}
s = s + Math.floor((n / amountFractionalBase) * 10).toString();
diff --git a/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx
b/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx
index b0e339c7..cfcef16d 100644
--- a/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx
+++ b/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx
@@ -22,7 +22,7 @@ export function ErrorMessage({ title, description }: {
title?: string|VNode; des
const [showErrorDetail, setShowErrorDetail] = useState(false);
if (!title)
return null;
- return <ErrorBox>
+ return <ErrorBox style={{paddingTop: 0, paddingBottom: 0}}>
<div>
<p>{title}</p>
{ description && <button onClick={() => { setShowErrorDetail(v => !v);
}}>
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx
b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index 0dbf34b5..0537621b 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -520,8 +520,7 @@ export const ErrorBox = styled.div`
justify-content: space-between;
flex-direction: column;
/* margin: 0.5em; */
- padding-left: 1em;
- padding-right: 1em;
+ padding: 1em;
/* width: 100%; */
color: #721c24;
background: #f8d7da;
@@ -539,6 +538,19 @@ export const ErrorBox = styled.div`
}
}
`
+
+export const SuccessBox = styled(ErrorBox)`
+ color: #0f5132;
+ background-color: #d1e7dd;
+ border-color: #badbcc;
+`
+
+export const WarningBox = styled(ErrorBox)`
+ color: #664d03;
+ background-color: #fff3cd;
+ border-color: #ffecb5;
+`
+
export const PopupNavigation = styled.div<{ devMode?: boolean }>`
background-color:#0042b2;
height: 35px;
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
index 3ca30ccb..622e7950 100644
--- a/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
@@ -30,7 +30,7 @@ export default {
},
};
-export const InsufficientBalance = createExample(TestedComponent, {
+export const NoBalance = createExample(TestedComponent, {
payStatus: {
status: PreparePayResultType.InsufficientBalance,
noncePriv: '',
@@ -46,6 +46,27 @@ export const InsufficientBalance =
createExample(TestedComponent, {
}
});
+export const NoEnoughBalance = createExample(TestedComponent, {
+ payStatus: {
+ status: PreparePayResultType.InsufficientBalance,
+ noncePriv: '',
+ proposalId: "proposal1234",
+ contractTerms: {
+ merchant: {
+ name: 'someone'
+ },
+ summary: 'some beers',
+ amount: 'USD:10',
+ } as Partial<ContractTerms> as any,
+ amountRaw: 'USD:10',
+ },
+ balance: {
+ currency: 'USD',
+ fraction: 40000000,
+ value: 9
+ }
+});
+
export const PaymentPossible = createExample(TestedComponent, {
uri:
'taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0',
payStatus: {
@@ -66,6 +87,26 @@ export const PaymentPossible =
createExample(TestedComponent, {
}
});
+export const PaymentPossibleWithFee = createExample(TestedComponent, {
+ uri:
'taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0',
+ payStatus: {
+ status: PreparePayResultType.PaymentPossible,
+ amountEffective: 'USD:10.20',
+ amountRaw: 'USD:10',
+ noncePriv: '',
+ contractTerms: {
+ nonce: '123213123',
+ merchant: {
+ name: 'someone'
+ },
+ amount: 'USD:10',
+ summary: 'some beers',
+ } as Partial<ContractTerms> as any,
+ contractTermsHash: '123456',
+ proposalId: 'proposal1234'
+ }
+});
+
export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
payStatus: {
status: PreparePayResultType.AlreadyConfirmed,
@@ -102,3 +143,22 @@ export const AlreadyConfirmedWithoutFullfilment =
createExample(TestedComponent,
paid: false,
}
});
+
+export const AlreadyPaid = createExample(TestedComponent, {
+ payStatus: {
+ status: PreparePayResultType.AlreadyConfirmed,
+ amountEffective: 'USD:10',
+ amountRaw: 'USD:10',
+ contractTerms: {
+ merchant: {
+ name: 'someone'
+ },
+ fulfillment_message: 'congratulations! you are looking at the
fulfillment message! ',
+ summary: 'some beers',
+ amount: 'USD:10',
+ } as Partial<ContractTerms> as any,
+ contractTermsHash: '123456',
+ proposalId: 'proposal1234',
+ paid: true,
+ }
+});
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx
b/packages/taler-wallet-webextension/src/cta/Pay.tsx
index c0038f8f..e7a3415a 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}`
}
diff --git a/packages/taler-wallet-webextension/src/hooks/useBalances.tsx
b/packages/taler-wallet-webextension/src/hooks/useBalances.tsx
index f12fca21..503b7a49 100644
--- a/packages/taler-wallet-webextension/src/hooks/useBalances.tsx
+++ b/packages/taler-wallet-webextension/src/hooks/useBalances.tsx
@@ -32,7 +32,6 @@ export type BalancesHook = BalancesHookOk | BalancesHookError
| undefined;
export function useBalances(): BalancesHook {
const [balance, setBalance] = useState<BalancesHook>(undefined);
- console.log('render balance')
useEffect(() => {
async function checkBalance() {
try {
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-wallet-core] branch master updated: some ui fixing from belen comments,
gnunet <=