From 7a600514c6d43bbaeba6b962533415e59fc46057 Mon Sep 17 00:00:00 2001
From: Sebastian <sebasjm@gmail.com>
Date: Mon, 8 Aug 2022 14:09:28 -0300
Subject: fixing #6096

merchant details and contract terms details factored out, to be used by other components
tests and stories updated
payment completed != confirmed (confirmed if paid by someone else)
---
 .../src/popup/BalancePage.tsx                      | 152 ++++++++++++++-------
 1 file changed, 104 insertions(+), 48 deletions(-)

(limited to 'packages/taler-wallet-webextension/src/popup/BalancePage.tsx')

diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index cdf507cb5..3275a0a07 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -23,8 +23,10 @@ import { Loading } from "../components/Loading.js";
 import { LoadingError } from "../components/LoadingError.js";
 import { MultiActionButton } from "../components/MultiActionButton.js";
 import { useTranslationContext } from "../context/translation.js";
-import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
+import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { Button } from "../mui/Button.js";
+import { ButtonHandler } from "../mui/handlers.js";
+import { compose, StateViewMap } from "../utils/index.js";
 import { AddNewActionView } from "../wallet/AddNewActionView.js";
 import * as wxApi from "../wxApi.js";
 import { NoBalanceHelp } from "./NoBalanceHelp.js";
@@ -34,17 +36,46 @@ export interface Props {
   goToWalletHistory: (currency: string) => Promise<void>;
   goToWalletManualWithdraw: () => Promise<void>;
 }
-export function BalancePage({
-  goToWalletManualWithdraw,
-  goToWalletDeposit,
-  goToWalletHistory,
-}: Props): VNode {
-  const { i18n } = useTranslationContext();
+
+export type State = State.Loading | State.Error | State.Action | State.Balances;
+
+export namespace State {
+  export interface Loading {
+    status: "loading";
+    error: undefined;
+  }
+
+  export interface Error {
+    status: "error";
+    error: HookError;
+  }
+
+  export interface Action {
+    status: "action";
+    error: undefined;
+    cancel: ButtonHandler;
+  }
+
+  export interface Balances {
+    status: "balance";
+    error: undefined;
+    balances: Balance[];
+    addAction: ButtonHandler;
+    goToWalletDeposit: (currency: string) => Promise<void>;
+    goToWalletHistory: (currency: string) => Promise<void>;
+    goToWalletManualWithdraw: ButtonHandler;
+  }
+}
+
+function useComponentState(
+  { goToWalletDeposit, goToWalletHistory, goToWalletManualWithdraw }: Props,
+  api: typeof wxApi,
+): State {
   const [addingAction, setAddingAction] = useState(false);
-  const state = useAsyncAsHook(wxApi.getBalance);
+  const state = useAsyncAsHook(api.getBalance);
 
   useEffect(() => {
-    return wxApi.onUpdateNotification(
+    return api.onUpdateNotification(
       [NotificationType.WithdrawGroupFinished],
       () => {
         state?.retry();
@@ -52,58 +83,80 @@ export function BalancePage({
     );
   });
 
-  const balances = !state || state.hasError ? [] : state.response.balances;
-
   if (!state) {
-    return <Loading />;
+    return {
+      status: "loading",
+      error: undefined,
+    };
   }
-
   if (state.hasError) {
-    return (
-      <LoadingError
-        title={<i18n.Translate>Could not load balance page</i18n.Translate>}
-        error={state}
-      />
-    );
+    return {
+      status: "error",
+      error: state,
+    };
   }
-
   if (addingAction) {
-    return <AddNewActionView onCancel={async () => setAddingAction(false)} />;
+    return {
+      status: "action",
+      error: undefined,
+      cancel: {
+        onClick: async () => setAddingAction(false),
+      },
+    };
   }
+  return {
+    status: "balance",
+    error: undefined,
+    balances: state.response.balances,
+    addAction: {
+      onClick: async () => setAddingAction(true),
+    },
+    goToWalletManualWithdraw: {
+      onClick: goToWalletManualWithdraw,
+    },
+    goToWalletDeposit,
+    goToWalletHistory,
+  };
+}
+
+const viewMapping: StateViewMap<State> = {
+  loading: Loading,
+  error: ErrorView,
+  action: ActionView,
+  balance: BalanceView,
+};
 
+export const BalancePage = compose(
+  "BalancePage",
+  (p: Props) => useComponentState(p, wxApi),
+  viewMapping,
+);
+
+function ErrorView({ error }: State.Error): VNode {
+  const { i18n } = useTranslationContext();
   return (
-    <BalanceView
-      balances={balances}
-      goToWalletManualWithdraw={goToWalletManualWithdraw}
-      goToWalletDeposit={goToWalletDeposit}
-      goToWalletHistory={goToWalletHistory}
-      goToAddAction={async () => setAddingAction(true)}
+    <LoadingError
+      title={<i18n.Translate>Could not load balance page</i18n.Translate>}
+      error={error}
     />
   );
 }
-export interface BalanceViewProps {
-  balances: Balance[];
-  goToWalletManualWithdraw: () => Promise<void>;
-  goToAddAction: () => Promise<void>;
-  goToWalletDeposit: (currency: string) => Promise<void>;
-  goToWalletHistory: (currency: string) => Promise<void>;
+
+function ActionView({ cancel }: State.Action): VNode {
+  return <AddNewActionView onCancel={cancel.onClick!} />;
 }
 
-export function BalanceView({
-  balances,
-  goToWalletManualWithdraw,
-  goToWalletDeposit,
-  goToWalletHistory,
-  goToAddAction,
-}: BalanceViewProps): VNode {
+export function BalanceView(state: State.Balances): VNode {
   const { i18n } = useTranslationContext();
-  const currencyWithNonZeroAmount = balances
+  const currencyWithNonZeroAmount = state.balances
     .filter((b) => !Amounts.isZero(b.available))
     .map((b) => b.available.split(":")[0]);
 
-  if (balances.length === 0) {
+  if (state.balances.length === 0) {
     return (
-      <NoBalanceHelp goToWalletManualWithdraw={goToWalletManualWithdraw} />
+      <NoBalanceHelp
+        goToWalletManualWithdraw={state.goToWalletManualWithdraw}
+      />
     );
   }
 
@@ -111,23 +164,26 @@ export function BalanceView({
     <Fragment>
       <section>
         <BalanceTable
-          balances={balances}
-          goToWalletHistory={goToWalletHistory}
+          balances={state.balances}
+          goToWalletHistory={state.goToWalletHistory}
         />
       </section>
       <footer style={{ justifyContent: "space-between" }}>
-        <Button variant="contained" onClick={goToWalletManualWithdraw}>
+        <Button
+          variant="contained"
+          onClick={state.goToWalletManualWithdraw.onClick}
+        >
           <i18n.Translate>Withdraw</i18n.Translate>
         </Button>
         {currencyWithNonZeroAmount.length > 0 && (
           <MultiActionButton
             label={(s) => <i18n.Translate>Deposit {s}</i18n.Translate>}
             actions={currencyWithNonZeroAmount}
-            onClick={(c) => goToWalletDeposit(c)}
+            onClick={(c) => state.goToWalletDeposit(c)}
           />
         )}
         <JustInDevMode>
-          <Button onClick={goToAddAction}>
+          <Button onClick={state.addAction.onClick}>
             <i18n.Translate>Enter URI</i18n.Translate>
           </Button>
         </JustInDevMode>
-- 
cgit v1.2.3

