gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]