gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant-backoffice] 01/02: copying pybank's look. WIP


From: gnunet
Subject: [taler-merchant-backoffice] 01/02: copying pybank's look. WIP
Date: Thu, 07 Apr 2022 07:34:17 +0200

This is an automated email from the git hooks/post-receive script.

ms pushed a commit to branch master
in repository merchant-backoffice.

commit af7f0fa9df6165e3d82246d4077ac2d4da6cb597
Author: ms <ms@taler.net>
AuthorDate: Tue Apr 5 10:47:50 2022 +0200

    copying pybank's look.  WIP
---
 packages/bank/src/components/QR.tsx    |   2 +-
 packages/bank/src/pages/home/index.tsx | 172 +++++++++++++++++++++++++--------
 2 files changed, 134 insertions(+), 40 deletions(-)

diff --git a/packages/bank/src/components/QR.tsx 
b/packages/bank/src/components/QR.tsx
index 9a05f60..f154dde 100644
--- a/packages/bank/src/components/QR.tsx
+++ b/packages/bank/src/components/QR.tsx
@@ -36,7 +36,7 @@ export function QR({ text }: { text: string }): VNode {
         width: "100%",
         display: "flex",
         flexDirection: "column",
-        alignItems: "center",
+        alignItems: "left",
       }}
     >
       <div
diff --git a/packages/bank/src/pages/home/index.tsx 
b/packages/bank/src/pages/home/index.tsx
index 03f0661..0c08c87 100644
--- a/packages/bank/src/pages/home/index.tsx
+++ b/packages/bank/src/pages/home/index.tsx
@@ -109,6 +109,9 @@ interface AccountStateType {
  * Helpers. *
  ***********/
 
+function genCaptchaNumbers(): string {
+  return `${Math.floor(Math.random() * 10)} + ${Math.floor(Math.random() * 
10)}`;
+}
 /**
  * Bring the state to show the public accounts page.
  */
@@ -124,7 +127,7 @@ function goPublicAccounts(pageStateSetter: 
StateUpdater<PageStateType>) {
 function validateAmount(maybeAmount: string): any {
   const amountRegex = "^[0-9]+(\.[0-9]+)?$";
   if (typeof maybeAmount !== "undefined" || maybeAmount !== "") {
-    console.log("Maybe valid amount", maybeAmount);
+    console.log("Maybe valid amount: " + maybeAmount);
     // tolerating comma instead of point.
     maybeAmount = maybeAmount.replace(",", ".");
     const re = RegExp(amountRegex)
@@ -515,9 +518,8 @@ async function createTransactionCall(
  * user should receive a QR code of the "taler://withdraw/" type and
  * supposed to scan it with their phone.
  *
- * TODO: (1) after the scan, the page should refresh itself and inform the
- * user about the operation's outcome.  (2) use POST helper.
- */
+ * TODO: (1) after the scan, the page should refresh itself and inform
+ * the user about the operation's outcome.  (2) use POST helper.  */
 async function createWithdrawalCall(
   amount: string,
   backendState: BackendStateTypeOpt,
@@ -563,7 +565,7 @@ async function createWithdrawalCall(
 
   console.log("Withdrawal operation created!");
   let resp = await res.json();
-  pageStateSetter((prevState) => ({
+  pageStateSetter((prevState: PageStateType) => ({
     ...prevState,
     withdrawalInProgress: true,
     talerWithdrawUri: resp.taler_withdraw_uri,
@@ -710,7 +712,7 @@ function BankFrame(Props: any): VNode {
         </div>
         <a href="https://taler.net/";>
         <img
-            src={talerLogo}
+          src={talerLogo}
          height="100"
          width="224"
          style="margin: 2em 2em">
@@ -815,7 +817,7 @@ function PaytoWireTransfer(Props: any): VNode {
           href="#"
           onClick={() => {
            console.log("switch to raw payto form");
-            pageStateSetter((prevState) => ({...prevState, isRawPayto: true}));
+            pageStateSetter((prevState: any) => ({...prevState, isRawPayto: 
true}));
          }}>{i18n`Want to try the raw payto://-format?`}
         </a></p>
       </div>
@@ -861,13 +863,107 @@ function PaytoWireTransfer(Props: any): VNode {
 }
 
 /**
- * Let user choose a amount and submit the withdtawal.
+ * Offer the QR code (and a clickable taler://-link) to
+ * permit the passing of exchange and reserve details to
+ * the bank.  Poll the backend until such operation is done.
+ */
+function TalerWithdrawalQRCode(Props: any): VNode {
+  const [pageState, pageStateSetter] = useContext(PageContext);
+  const {
+    withdrawalId,
+    talerWithdrawUri,
+    accountLabel,
+    backendState } = Props;
+  const i18n = useTranslator();
+  console.log(`Showing withdraw URI: ${talerWithdrawUri}`);
+  // polling the wallet:
+  const { data, error } = useSWR(
+    
`integration-api/accounts/${accountLabel}/withdrawal-operation/${withdrawalId}`
+  );
+  const captchaNumbers = {
+    a: Math.floor(Math.random() * 10),
+    b: Math.floor(Math.random() * 10)
+  }
+  var captchaAnswer = "";
+  // fall here as long as the wallet did NOT communicate:
+  if (typeof error !== "undefined") {
+    console.log("transactions not found error", error);
+    switch(error.status) {
+      case 404: {
+        return (<section id="main" class="content">
+          <h1 class="nav">{i18n`Withdraw to a Taler Wallet`}</h1>
+          <p>{i18n`You can use this QR code to withdraw to your mobile 
wallet:`}</p>
+          {QR({text: talerWithdrawUri})}
+          <p>Click <a href={talerWithdrawUri}>{i18n`this link`}</a> to open 
your Taler wallet!</p>
+          <br /><br />
+          <button onClick={() => {
+            pageStateSetter((prevState: PageStateType) => {
+              const { withdrawalOutcome, withdrawalId, talerWithdrawUri, 
...rest } = prevState;
+              return { ...rest, withdrawalInProgress: false };
+          })}}>{i18n`Close`}</button>
+        </section>);
+      }
+      default: {
+        pageStateSetter((prevState: PageStateType) => ({...prevState, 
hasError: true, error: error }))
+        return <p>Could not complete the withdrawal: {error}</p>
+      }
+    }
+  }
+  // here the reserve public key and exchange payment details are known to the 
bank,
+  // ask for a confirmation (used to be the CAPTCHA page):
+  return (<Fragment>
+    <h1 class="nav">{i18n`Confirm Withdrawal`}</h1>
+    <p><Translate>
+      Please, authorize this operation by answering the following question.
+    </Translate></p>
+    <div>
+      <label>What is <em>{captchaNumbers.a} + {captchaNumbers.b}</em> 
?&nbsp;</label>
+      <input
+        type="text"
+       required
+        onInput={(e): void => {
+          captchaAnswer = e.currentTarget.value;
+        }} />
+      <input
+        type="submit"
+        value="confirm"
+        onClick={ () => {
+          if (captchaAnswer == (captchaNumbers.a + 
captchaNumbers.b).toString()) {
+            confirmWithdrawalCall(
+              backendState,
+              pageState.withdrawalId,
+              pageStateSetter)
+           return;
+         }
+          pageStateSetter((prevState: PageStateType) =>
+           ({...prevState, hasError: true, error: "Answer is wrong."}))
+      }} />
+      <input
+        type="submit"
+        value="abort"
+        onClick={ () =>
+         abortWithdrawalCall(
+            backendState,
+            pageState.withdrawalId,
+            pageStateSetter
+         )} />
+    </div>
+    <p><Translate>
+      A this point, a <b>real</b> bank would ask for an additional
+      authentication proof (PIN/TAN, one time password, ..), instead
+      of a simple calculation.
+    </Translate></p>
+  </Fragment>);
+}
+
+/**
+ * Let the user choose an amount and submit the withdtawal.
  */
 function TalerWithdrawal(Props: any): VNode {
   const {backendState, pageStateSetter} = Props;
   const currency = useContext(CurrencyContext);
   const i18n = useTranslator();
-  var submitAmount = ""; // without currency.
+  var submitAmount = "5.00"; // must match the first <select> child.
   const amountRegex = "^[0-9]+(\.[0-9]+)?$";
 
   var submitButton = <input
@@ -893,10 +989,14 @@ function TalerWithdrawal(Props: any): VNode {
       <div>
         <h2>{i18n`Withdraw Money into a Taler wallet`}</h2>
         <div id="reserve-form"
-            class="pure-form"
-            name="tform">
+             class="pure-form"
+             name="tform">
           {i18n`Amount to withdraw`}:&nbsp;
-          <select id="reserve-amount" name="withdraw-amount" class="amount" 
autofocus>
+          <select id="reserve-amount"
+                 name="withdraw-amount"
+                 class="amount" autofocus
+                  onChange={(e): void => {
+                   submitAmount = e.currentTarget.value; }}>
             <option value="5.00">5.00</option>
             <option value="10.00">10.00</option>
             <option value="15.00">15.00</option>
@@ -1092,6 +1192,7 @@ function Account(Props: any): VNode {
     tryManualTransfer,
     withdrawalOutcome,
     transferOutcome,
+    withdrawalId,
     talerWithdrawUri } = pageState;
   const i18n = useTranslator();
   const logOut = (
@@ -1201,14 +1302,17 @@ function Account(Props: any): VNode {
    * the outcome.
    */
   if (talerWithdrawUri) {
-    console.log(`Showing withdraw URI: ${talerWithdrawUri}`);
-    return (<Fragment>
-      <p>Scan the following QR code, and then confirm!</p>
-      <div>{QR({text: talerWithdrawUri})}</div>
-      <a href={talerWithdrawUri}></a>
-      <p>Withdraw address: <pre>{talerWithdrawUri}</pre></p>
-      {Props.children}
-    </Fragment>);
+    console.log("Bank created a new Taler withdrawal");
+    return (
+      <BankFrame>
+        {logOut}<br />
+        <TalerWithdrawalQRCode
+         accountLabel={accountLabel}
+         backendState={backendState}
+         withdrawalId={withdrawalId}
+         talerWithdrawUri={talerWithdrawUri} />
+      </BankFrame>
+    );
   }
   const balance = parseAmount(data.balance.amount)
   if (tryManualTransfer) {
@@ -1231,13 +1335,10 @@ function Account(Props: any): VNode {
     </section>
     <CurrencyContext.Provider value={balance.currency}>
       {Props.children}
+      <TalerWithdrawal
+        backendState={backendState}
+        pageStateSetter={pageStateSetter} />
     </CurrencyContext.Provider>
-    {
-      withdrawalInProgress && !transferOutcome &&
-        <TalerWithdrawal
-          backendState={backendState}
-          pageStateSetter={pageStateSetter} />
-    }
     <section id="main">
       <article>
         <h2>{i18n`Latest transactions:`}</h2>
@@ -1416,19 +1517,10 @@ export function BankHome(): VNode {
           backendUrl={backendState.url}>
         <PageContext.Provider value={[pageState, pageStateSetter]}>
           <Account accountLabel={backendState.username} 
backendState={backendState}>
-  
-            { /**
-               * No action is currently being performed (page is 'pristine'):
-               * offer the Taler withdrawal button.
-               */
-              !pageState.withdrawalInProgress && !pageState.transferOutcome && 
<TalerWithdrawal
-                backendState={backendState}
-               pageStateSetter={pageStateSetter} />
-            }
-  
             { /**
                * Wire transfer reached a persisten state: offer to
-               * return back to the pristine profile page.
+               * return back to the pristine profile page.  FIXME:
+              * move this into the Account component.
                */
               pageState.transferOutcome && <button onClick={() => {
                 pageStateSetter((prevState) => {
@@ -1438,7 +1530,8 @@ export function BankHome(): VNode {
   
             { /**
                * Withdrawal reached a persisten state: offer to
-               * return back to the pristine profile page.
+               * return back to the pristine profile page.  FIXME:
+              * move this into the Account component.
                */
               pageState.withdrawalOutcome && <button onClick={() => {
                 pageStateSetter((prevState) => {
@@ -1452,7 +1545,8 @@ export function BankHome(): VNode {
   
             { /**
                * The withdrawal QR code is rendered: offer to confirm
-               * or abort the operation.
+               * or abort the operation.  FIXME: move this into the Account
+              * component.
                */
               pageState.talerWithdrawUri && <div><button onClick={() => {
                 confirmWithdrawalCall(

-- 
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]