From a3aa7d95d09c83794067c47df4a455c0e3f21806 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Fri, 7 Apr 2023 17:30:01 -0300
Subject: anon withdrawal confirmation, and fix error with infinity loop

---
 packages/demobank-ui/src/pages/HomePage.tsx | 197 +++++++++++++---------------
 1 file changed, 93 insertions(+), 104 deletions(-)

(limited to 'packages/demobank-ui/src/pages/HomePage.tsx')

diff --git a/packages/demobank-ui/src/pages/HomePage.tsx b/packages/demobank-ui/src/pages/HomePage.tsx
index 7ef4284bf..0a5a61396 100644
--- a/packages/demobank-ui/src/pages/HomePage.tsx
+++ b/packages/demobank-ui/src/pages/HomePage.tsx
@@ -14,16 +14,30 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { Logger } from "@gnu-taler/taler-util";
+import {
+  HttpStatusCode,
+  Logger,
+  parseWithdrawUri,
+  stringifyWithdrawUri,
+} from "@gnu-taler/taler-util";
 import {
   ErrorType,
+  HttpResponse,
   HttpResponsePaginated,
   useTranslationContext,
 } from "@gnu-taler/web-util/lib/index.browser";
-import { Fragment, h, VNode } from "preact";
+import { Fragment, VNode, h } from "preact";
+import { StateUpdater } from "preact/hooks";
 import { Loading } from "../components/Loading.js";
 import { useBackendContext } from "../context/backend.js";
-import { PageStateType, usePageContext } from "../context/pageState.js";
+import {
+  ObservedStateType,
+  PageStateType,
+  notifyError,
+  notifyInfo,
+  usePageContext,
+} from "../context/pageState.js";
+import { getInitialBackendBaseURL } from "../hooks/backend.js";
 import { AccountPage } from "./AccountPage.js";
 import { AdminPage } from "./AdminPage.js";
 import { LoginForm } from "./LoginForm.js";
@@ -41,133 +55,109 @@ const logger = new Logger("AccountPage");
  * @param param0
  * @returns
  */
-export function HomePage({ onRegister }: { onRegister: () => void }): VNode {
+export function HomePage({
+  onRegister,
+  onPendingOperationFound,
+}: {
+  onPendingOperationFound: (id: string) => void;
+  onRegister: () => void;
+}): VNode {
   const backend = useBackendContext();
   const { pageState, pageStateSetter } = usePageContext();
   const { i18n } = useTranslationContext();
 
-  function saveError(error: PageStateType["error"]): void {
-    pageStateSetter((prev) => ({ ...prev, error }));
-  }
-
-  function saveErrorAndLogout(error: PageStateType["error"]): void {
-    saveError(error);
-    backend.logOut();
-  }
-
-  function clearCurrentWithdrawal(): void {
-    pageStateSetter((prevState: PageStateType) => {
-      return {
-        ...prevState,
-        withdrawalId: undefined,
-        talerWithdrawUri: undefined,
-        withdrawalInProgress: false,
-      };
-    });
-  }
-
   if (backend.state.status === "loggedOut") {
     return <LoginForm onRegister={onRegister} />;
   }
 
-  const { withdrawalId, talerWithdrawUri } = pageState;
-
-  if (talerWithdrawUri && withdrawalId) {
-    return (
-      <WithdrawalQRCode
-        account={backend.state.username}
-        withdrawalId={withdrawalId}
-        talerWithdrawUri={talerWithdrawUri}
-        onConfirmed={() => {
-          pageStateSetter((prevState) => {
-            const { talerWithdrawUri, ...rest } = prevState;
-            // remove talerWithdrawUri and add info
-            return {
-              ...rest,
-              info: i18n.str`Withdrawal confirmed!`,
-            };
-          });
-        }}
-        onError={(error) => {
-          pageStateSetter((prevState) => {
-            const { talerWithdrawUri, ...rest } = prevState;
-            // remove talerWithdrawUri and add error
-            return {
-              ...rest,
-              error,
-            };
-          });
-        }}
-        onAborted={clearCurrentWithdrawal}
-        onLoadNotOk={handleNotOkResult(
-          backend.state.username,
-          saveError,
-          i18n,
-          onRegister,
-        )}
-      />
-    );
+  if (pageState.currentWithdrawalOperationId) {
+    onPendingOperationFound(pageState.currentWithdrawalOperationId);
+    return <Loading />;
   }
 
   if (backend.state.isUserAdministrator) {
-    return (
-      <AdminPage
-        onLoadNotOk={handleNotOkResult(
-          backend.state.username,
-          saveErrorAndLogout,
-          i18n,
-          onRegister,
-        )}
-      />
-    );
+    return <AdminPage onRegister={onRegister} />;
   }
 
   return (
     <AccountPage
       account={backend.state.username}
-      onLoadNotOk={handleNotOkResult(
-        backend.state.username,
-        saveErrorAndLogout,
-        i18n,
-        onRegister,
-      )}
+      onLoadNotOk={handleNotOkResult(i18n, onRegister)}
+    />
+  );
+}
+
+export function WithdrawalOperationPage({
+  operationId,
+  onLoadNotOk,
+  onAbort,
+}: {
+  operationId: string;
+  onLoadNotOk: () => void;
+  onAbort: () => void;
+}): VNode {
+  const uri = stringifyWithdrawUri({
+    bankIntegrationApiBaseUrl: getInitialBackendBaseURL(),
+    withdrawalOperationId: operationId,
+  });
+  const parsedUri = parseWithdrawUri(uri);
+  const { i18n } = useTranslationContext();
+  const { pageStateSetter } = usePageContext();
+  function clearCurrentWithdrawal(): void {
+    pageStateSetter({});
+    onAbort();
+  }
+
+  if (!parsedUri) {
+    notifyError({
+      title: i18n.str`The Withdrawal URI is not valid: "${uri}"`,
+    });
+    return <Loading />;
+  }
+
+  return (
+    <WithdrawalQRCode
+      withdrawUri={parsedUri}
+      onConfirmed={() => {
+        notifyInfo(i18n.str`Withdrawal confirmed!`);
+      }}
+      onAborted={clearCurrentWithdrawal}
+      onLoadNotOk={onLoadNotOk}
     />
   );
 }
 
-function handleNotOkResult(
-  account: string,
-  onErrorHandler: (state: PageStateType["error"]) => void,
+export function handleNotOkResult(
   i18n: ReturnType<typeof useTranslationContext>["i18n"],
-  onRegister: () => void,
-): <T>(result: HttpResponsePaginated<T, SandboxBackend.SandboxError>) => VNode {
+  onRegister?: () => void,
+): <T>(
+  result:
+    | HttpResponsePaginated<T, SandboxBackend.SandboxError>
+    | HttpResponse<T, SandboxBackend.SandboxError>,
+) => VNode {
   return function handleNotOkResult2<T>(
-    result: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+    result:
+      | HttpResponsePaginated<T, SandboxBackend.SandboxError>
+      | HttpResponse<T, SandboxBackend.SandboxError>,
   ): VNode {
-    if (result.clientError && result.isUnauthorized) {
-      onErrorHandler({
-        title: i18n.str`Wrong credentials for "${account}"`,
-      });
-      return <LoginForm onRegister={onRegister} />;
-    }
-    if (result.clientError && result.isNotfound) {
-      onErrorHandler({
-        title: i18n.str`Username or account label "${account}" not found`,
-      });
-      return <LoginForm onRegister={onRegister} />;
-    }
     if (result.loading) return <Loading />;
     if (!result.ok) {
       switch (result.type) {
         case ErrorType.TIMEOUT: {
-          onErrorHandler({
+          notifyError({
             title: i18n.str`Request timeout, try again later.`,
           });
           break;
         }
         case ErrorType.CLIENT: {
+          if (result.status === HttpStatusCode.Unauthorized) {
+            notifyError({
+              title: i18n.str`Wrong credentials`,
+            });
+            return <LoginForm onRegister={onRegister} />;
+          }
           const errorData = result.payload;
-          onErrorHandler({
+          notifyError({
             title: i18n.str`Could not load due to a client error`,
             description: errorData.error.description,
             debug: JSON.stringify(result),
@@ -175,19 +165,18 @@ function handleNotOkResult(
           break;
         }
         case ErrorType.SERVER: {
-          const errorData = result.error;
-          onErrorHandler({
+          notifyError({
             title: i18n.str`Server returned with error`,
-            description: errorData.error.description,
-            debug: JSON.stringify(result),
+            description: result.payload.error.description,
+            debug: JSON.stringify(result.payload),
           });
           break;
         }
         case ErrorType.UNEXPECTED: {
-          onErrorHandler({
+          notifyError({
             title: i18n.str`Unexpected error.`,
             description: `Diagnostic from ${result.info?.url} is "${result.message}"`,
-            debug: JSON.stringify(result.exception),
+            debug: JSON.stringify(result),
           });
           break;
         }
@@ -196,7 +185,7 @@ function handleNotOkResult(
         }
       }
 
-      return <LoginForm onRegister={onRegister} />;
+      return <div>error</div>;
     }
     return <div />;
   };
-- 
cgit v1.2.3

