gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant-backoffice] branch master updated: copying pybank's look


From: gnunet
Subject: [taler-merchant-backoffice] branch master updated: copying pybank's look. WIP
Date: Mon, 04 Apr 2022 17:55:03 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 1e8fbfc  copying pybank's look.  WIP
1e8fbfc is described below

commit 1e8fbfc481346f39cc05a7532dcfb92a8240a7d4
Author: ms <ms@taler.net>
AuthorDate: Mon Apr 4 17:52:49 2022 +0200

    copying pybank's look.  WIP
---
 packages/bank/src/pages/home/index.tsx | 303 ++++++++++++++++++++++-----------
 1 file changed, 199 insertions(+), 104 deletions(-)

diff --git a/packages/bank/src/pages/home/index.tsx 
b/packages/bank/src/pages/home/index.tsx
index 070d091..03f0661 100644
--- a/packages/bank/src/pages/home/index.tsx
+++ b/packages/bank/src/pages/home/index.tsx
@@ -80,7 +80,9 @@ interface Amount {
  */
 interface PageStateType {
   isLoggedIn: boolean;
+  isRawPayto: boolean;
   tryRegister: boolean;
+  tryManualTransfer: boolean;
   showPublicHistories: boolean;
   hasError: boolean;
   withdrawalInProgress: boolean;
@@ -119,7 +121,7 @@ function goPublicAccounts(pageStateSetter: 
StateUpdater<PageStateType>) {
  * replace comma with a dot.  Returns 'false' whenever
  * the input is invalid, the valid amount otherwise.
  */
-function validateAmount(maybeAmount: string): string {
+function validateAmount(maybeAmount: string): any {
   const amountRegex = "^[0-9]+(\.[0-9]+)?$";
   if (typeof maybeAmount !== "undefined" || maybeAmount !== "") {
     console.log("Maybe valid amount", maybeAmount);
@@ -278,7 +280,9 @@ function useAccountState(
 function usePageState(
   state: PageStateType = {
     isLoggedIn: false,
+    isRawPayto: false,
     tryRegister: false,
+    tryManualTransfer: false,
     showPublicHistories: false,
     hasError: false,
     withdrawalInProgress: false,
@@ -668,14 +672,17 @@ async function registrationCall(
  * Functional components. *
  *************************/
 
-function ErrorBanner(Props: any): VNode {
+function ErrorBanner(Props: any): VNode | null {
   const [pageState, pageStateSetter] = Props.pageState;
   const i18n = useTranslator();
-  if (!pageState.hasError) return;
+  if (!pageState.hasError) return null;
   return (
     <p class="informational informational-fail">{pageState.error}
       &nbsp;&nbsp;<a href="#" onClick={() => {
-        pageStateSetter((prevState: PageStateType) =>({...prevState, hasError: 
false}))}}>
+        pageStateSetter(function (prevState: PageStateType) {
+          delete prevState.error; // delete error message
+         return {...prevState, hasError: false} // delete error state
+       })}}>
         {i18n`Clear`}
       </a>
     </p>);
@@ -698,7 +705,7 @@ function BankFrame(Props: any): VNode {
          This part of the demo shows how a bank that supports
          Taler directly would work. In addition to using your own
          bank account, you can also see the transaction history of
-         some <a href="#" onclick={goPublicAccounts(pageStateSetter)}>Public 
Accounts</a>.
+         some <a href="#" onClick={goPublicAccounts(pageStateSetter)}>Public 
Accounts</a>.
        </Translate></p>
         </div>
         <a href="https://taler.net/";>
@@ -737,51 +744,120 @@ function BankFrame(Props: any): VNode {
 }
 
 function PaytoWireTransfer(Props: any): VNode {
-  const {backendState, pageStateSetter} = Props;
   const currency = useContext(CurrencyContext);
+  const [pageState, pageStateSetter] = useContext(PageContext); // NOTE: used 
for go-back button?
   const i18n = useTranslator();
   const amountRegex = "^[0-9]+(\.[0-9]+)?$";
+  const ibanRegex = "^[A-Z][A-Z][0-9]+$";
   var amountInput = "";
+  var receiverInput = "";
+  var subjectInput = "";
   var transactionData: TransactionRequestType;
-
-  return <div>
-    <input
-      type="text"
-      placeholder="amount"
-      pattern={amountRegex}
-      onInput={(e): void => {
-        amountInput = e.currentTarget.value;
-      }} />
-    <label>{currency}</label> 
-    <input
-      type="text"
-      placeholder="payto address" // changing this breaks tests.
-      required
-      onInput={(e): void => {
-        transactionData = {
-          ...transactionData,
-          paytoUri: e.currentTarget.value,
-        };
-      }} />
-    <button onClick={() => {
-      amountInput = validateAmount(amountInput);
-      /**
-       * By invalid amounts, the validator prints error messages
-       * on the console, and the browser colourizes the amount input
-       * box to indicate a error.
-       */
-      if (!amountInput) return;
-      transactionData = {
-        ...transactionData,
-        amount: `${currency}:${amountInput}`
-      };
-      createTransactionCall(
-        transactionData,
-        backendState,
-        pageStateSetter
-      ); 
-    }}>{i18n`Create wire transfer`}</button>
-  </div>
+  
+  console.log("wire form page state", pageState);
+  const goBackForm = <a href="#" onClick={
+    () => pageStateSetter((prevState: PageStateType) => ({...prevState, 
tryManualTransfer: false})) 
+  }>{i18n`Go back`}</a>;
+  const goBackRawPayto = <a href="#" onClick={
+    () => pageStateSetter((prevState: PageStateType) => ({...prevState, 
isRawPayto: false})) 
+  }>{i18n`Go back`}</a>;
+  if (!pageState.isRawPayto) {
+    console.log("wire transfer form");
+    return (<article>
+      <div>
+        <h2>{i18n`Wire transfer`}</h2>
+        <p>{i18n`Transfer money to another account of this bank:`}<br /><br 
/></p>
+        <div name="wire-transfer-form">
+          <input
+            type="text"
+            placeholder="receiver iban"
+           required
+            pattern={ibanRegex}
+            onInput={(e): void => {
+              receiverInput = e.currentTarget.value;
+            }} /><br /><br />
+          <input
+            type="text"
+            placeholder="subject"
+            onInput={(e): void => {
+              subjectInput = e.currentTarget.value;
+            }} /><br /><br />
+          <input
+            type="text"
+            placeholder="amount"
+            pattern={amountRegex}
+            onInput={(e): void => {
+              amountInput = e.currentTarget.value;
+            }} />&nbsp;<label>{`${currency}:X.Y`}</label><br /><br />
+          <input
+            type="submit"
+            onClick={() => {
+              amountInput = validateAmount(amountInput);
+              /**
+               * By invalid amounts, the validator prints error messages
+               * on the console, and the browser colourizes the amount input
+               * box to indicate a error.
+               */
+              if (!amountInput) return;
+              if (!RegExp(ibanRegex).test(receiverInput)) return;
+              transactionData = {
+                paytoUri: 
`payto://iban/${receiverInput}?message=${subjectInput}`,
+                amount: `${currency}:${amountInput}`
+              };
+              createTransactionCall(
+                transactionData,
+                Props.backendState,
+                pageStateSetter
+              ); 
+            }}  />
+        </div>
+        <p><a
+          href="#"
+          onClick={() => {
+           console.log("switch to raw payto form");
+            pageStateSetter((prevState) => ({...prevState, isRawPayto: true}));
+         }}>{i18n`Want to try the raw payto://-format?`}
+        </a></p>
+      </div>
+      {goBackForm}
+    </article>);
+  }
+  console.log("rendering raw payto form");
+  return (<article>
+    <div>
+      <h2>{i18n`Wire transfer`}</h2>
+      <p>{i18n`Transfer money via the Payto system:`}<br /><br />
+        Address pattern: <code style="font-size: 15px">
+         payto://iban/[receiver-iban]?message=[subject]&amount=[{currency}:X.Y]
+       </code>
+      </p>
+      <div name="payto-form">
+        <input name="address"
+          size={90}
+          required
+          placeholder={i18n`payto address`}
+          
pattern="payto://x-taler-bank/[a-z\.]+(:[0-9]+)?/[0-9a-zA-Z]+\?message=[a-zA-Z0-9
 ]+&amount={currency}:[0-9]+(\.[0-9]+)?"
+          onInput={(e): void => {
+          transactionData = {
+            ...transactionData,
+            paytoUri: e.currentTarget.value,
+          };
+        }} />
+        <input class="pure-button pure-button-primary"
+               type="submit"
+               value={i18n`Confirm`}
+              onClick={() => {
+                 if (typeof transactionData.paytoUri === "undefined" ||
+                     transactionData.paytoUri.length === 0) return;
+                   createTransactionCall(
+                     transactionData,
+                     Props.backendState,
+                     pageStateSetter); 
+               }} />
+      </div>
+    </div>
+    <p>{goBackRawPayto}</p>
+  </article>);
 }
 
 /**
@@ -794,7 +870,11 @@ function TalerWithdrawal(Props: any): VNode {
   var submitAmount = ""; // without currency.
   const amountRegex = "^[0-9]+(\.[0-9]+)?$";
 
-  var submitButton = <button
+  var submitButton = <input
+      id="select-exchange"
+      class="pure-button pure-button-primary"
+      type="submit"
+      value={i18n`Start withdrawal`}
     onClick={() => {
       submitAmount = validateAmount(submitAmount);
       /**
@@ -807,17 +887,15 @@ function TalerWithdrawal(Props: any): VNode {
         `${currency}:${submitAmount}`,
         backendState,
         pageStateSetter
-      )}}>{i18n`Charge Taler wallet`}
-    </button>;
+      )}} />;
 
     return (<article>
       <div>
         <h2>{i18n`Withdraw Money into a Taler wallet`}</h2>
         <div id="reserve-form"
             class="pure-form"
-            method="post"
             name="tform">
-          {i18n`Amount to withdraw`}
+          {i18n`Amount to withdraw`}:&nbsp;
           <select id="reserve-amount" name="withdraw-amount" class="amount" 
autofocus>
             <option value="5.00">5.00</option>
             <option value="10.00">10.00</option>
@@ -828,9 +906,9 @@ function TalerWithdrawal(Props: any): VNode {
              type="text"
              readonly
              class="currency-indicator"
-             size={balance.currency.length}
-             tabindex="-1" value="{{ currency }}" />
-         {submitButton}
+             size={currency.length}
+             tabIndex={-1} value={currency} />
+         &nbsp;{submitButton}
         </div>
       </div>
     </article>);
@@ -885,7 +963,7 @@ function LoginForm(Props: any): VNode {
  */
 function RegistrationForm(Props: any): VNode {
   const [pageState, pageStateSetter] = useContext(PageContext);
-  var submitData: CredentialsRequestType = {};
+  var submitData: CredentialsRequestType;
   const i18n = useTranslator();
 
   return (
@@ -924,8 +1002,10 @@ function RegistrationForm(Props: any): VNode {
               <button
                 class="pure-button pure-button-primary"
                 onClick={() => {
+                 console.log("maybe submitting the registration..");
                  if (!("password" in submitData) || !("username" in 
submitData)) return;
                  if (submitData.password.length === 0 || 
submitData.username.length === 0) return;
+                 console.log("submitting the registration..");
                   registrationCall(
                     submitData,
                     Props.backendStateSetter, // will store BE URL, if OK.
@@ -1000,15 +1080,41 @@ function Transactions(Props: any): VNode {
 }
 
 /**
- * Show only the account's balance.
+ * Show only the account's balance.  NOTE: the backend state
+ * is mostly needed to provide the user's credentials to POST
+ * to the bank.
  */
 function Account(Props: any): VNode {
+  const { accountLabel, backendState } = Props;
+  const [pageState, pageStateSetter] = useContext(PageContext);
   const {
+    withdrawalInProgress,
+    tryManualTransfer,
     withdrawalOutcome,
     transferOutcome,
-    talerWithdrawUri,
-    accountLabel } = Props;
-  const pageState = useContext(PageContext);
+    talerWithdrawUri } = pageState;
+  const i18n = useTranslator();
+  const logOut = (
+    <a
+      href="#"
+      class="pure-button logout-button"
+      onClick={() => {
+        setTxPageNumber(0);
+        pageStateSetter((prevState: PageStateType) => {
+          const {
+            talerWithdrawUri,
+            withdrawalOutcome,
+            withdrawalId, ...rest } = prevState;
+          return {
+            ...rest,
+            isLoggedIn: false,
+            withdrawalInProgress: false,
+            isRawPayto: false,
+            tryManualTransfer: false,
+          };
+        });
+      }}>[{i18n`Logout`}]</a>);
+
   /**
    * This part shows a list of transactions: with 5 elements by
    * default and offers a "load more" button.
@@ -1018,30 +1124,28 @@ function Account(Props: any): VNode {
   for (let i = 0; i <= txPageNumber; i++) {
     txsPages.push(<Transactions accountLabel={accountLabel} pageNumber={i} />)
   }
-  const i18n = useTranslator();
   /**
    * Getting the bank account balance.
    */
   const { data, error } = useSWR(`access-api/accounts/${accountLabel}`);
   if (typeof error !== "undefined") {
     console.log("account error", error);
-
     /**
      * FIXME: try only one invocation of pageStateSetter,
      * after having decided the error message in the case-branch.
      */
     switch(error.status) {
       case 404: {
-        pageState[1]((prevState) => ({
+        pageStateSetter((prevState: PageStateType) => ({
           ...prevState,
           hasError: true,
           isLoggedIn: false,
-         error: i18n`Username or account label not found.`
+         error: i18n`Username or account label '${accountLabel}' not found.  
Won't login.`
         }));
         return <p>Profile not found...</p>;
       }
       case 401: {
-        pageState[1]((prevState) => ({
+        pageStateSetter((prevState: PageStateType) => ({
           ...prevState,
           hasError: true,
           isLoggedIn: false,
@@ -1050,7 +1154,7 @@ function Account(Props: any): VNode {
         return <p>Wrong credentials...</p>;
       }
       default: {
-        pageState[1]((prevState) => ({
+        pageStateSetter((prevState: PageStateType) => ({
           ...prevState,
           hasError: true,
           isLoggedIn: false,
@@ -1107,28 +1211,43 @@ function Account(Props: any): VNode {
     </Fragment>);
   }
   const balance = parseAmount(data.balance.amount)
+  if (tryManualTransfer) {
+    return (
+      <BankFrame>
+       {logOut}<br />
+        <CurrencyContext.Provider value={balance.currency}>
+          <PaytoWireTransfer backendState={backendState} />
+      </CurrencyContext.Provider></BankFrame>);
+  }
   return (<BankFrame>
     <div>
       <h1 class="nav">
        <Translate>Welcome, {accountLabel} 
({getIbanFromPayto(data.paytoUri)})!</Translate>
       </h1>
-      <a
-        href="#"
-        class="pure-button logout-button"
-        onClick={() => {
-          setTxPageNumber(0);
-          pageStateSetter((prevState) => {
-            const {
-              talerWithdrawUri,
-              withdrawalOutcome,
-              withdrawalId, ...rest } = prevState;
-              return {...rest, isLoggedIn: false, withdrawalInProgress: false};
-          })
-          }}>[{i18n`Logout`}]</a><br />
+      {logOut}<br />
     </div>
     <section id="menu">
       <p>{i18n`Bank account balance:`} <br /> <b>{`${balance.value} 
${balance.currency}`}</b></p>
     </section>
+    <CurrencyContext.Provider value={balance.currency}>
+      {Props.children}
+    </CurrencyContext.Provider>
+    {
+      withdrawalInProgress && !transferOutcome &&
+        <TalerWithdrawal
+          backendState={backendState}
+          pageStateSetter={pageStateSetter} />
+    }
+    <section id="main">
+      <article>
+        <h2>{i18n`Latest transactions:`}</h2>
+        <Transactions pageNumber="0" accountLabel={accountLabel} />
+        <p><a href="#" onClick={() =>
+          pageStateSetter((prevState: PageStateType) =>
+           ({...prevState, tryManualTransfer: true}))
+       }>{i18n`Transfer money manually`}</a></p>
+      </article>
+    </section>
   </BankFrame>);
 }
 
@@ -1191,23 +1310,21 @@ function PublicHistories(Props: any): VNode {
     switch(error.status) {
       case 404: {
         console.log("public accounts: 404", error);
-        Props.pageStateSetter((prevState) => ({
+        Props.pageStateSetter((prevState: PageStateType) => ({
           ...prevState,
           hasError: true,
           showPublicHistories: false,
          error: i18n`List of public accounts was not found.`
         }));
-        return;
       }
       default: {
         console.log("public accounts: non-404 error", error);
-        Props.pageStateSetter((prevState) => ({
+        Props.pageStateSetter((prevState: PageStateType) => ({
           ...prevState,
           hasError: true,
           showPublicHistories: false,
          error: i18n`List of public accounts could not be retrieved.`
         }));
-        return;
       }
     }
   }
@@ -1298,7 +1415,7 @@ export function BankHome(): VNode {
           password={backendState.password}
           backendUrl={backendState.url}>
         <PageContext.Provider value={[pageState, pageStateSetter]}>
-          <Account>
+          <Account accountLabel={backendState.username} 
backendState={backendState}>
   
             { /**
                * No action is currently being performed (page is 'pristine'):
@@ -1349,15 +1466,6 @@ export function BankHome(): VNode {
                     pageStateSetter);}}>{i18n`Abort withdrawal`}</button>
               </div>
             }
-  
-            { /**
-               * Profile page is pristine: offer the wire transfer form.
-               */
-              !pageState.withdrawalInProgress &&
-                !pageState.transferOutcome &&
-                  <PaytoWireTransfer pageStateSetter={pageStateSetter}
-                                    backendState={backendState} />
-            }
           </Account>
         </PageContext.Provider>
       </SWRWithCredentials>
@@ -1388,16 +1496,3 @@ export function BankHome(): VNode {
     </PageContext.Provider>
   );
 }
-
-/*
-<SWRWithoutCredentials baseUrl={getRootPath()}>
-        <LoginForm
-         pageStateSetter={pageStateSetter}
-          backendStateSetter={backendStateSetter} />
-       <p>Not a customer yet?  <a onClick={() => {
-          pageStateSetter((prevState) => ({...prevState, tryRegister: 
true}))}}>Register!</a></p>
-       <p>See our public <a onClick={() => {
-          pageStateSetter((prevState) => (
-            {...prevState, showPublicHistories: true}))}}>transactions</a></p>
-      </SWRWithoutCredentials>
-*/

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