gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 01/02: manage account instead of add account


From: gnunet
Subject: [taler-wallet-core] 01/02: manage account instead of add account
Date: Sun, 30 Oct 2022 00:55:18 +0200

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

sebasjm pushed a commit to branch master
in repository wallet-core.

commit fe6e9be70225cf2953822ff64b9e90066cab97ea
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Oct 28 13:39:06 2022 -0300

    manage account instead of add account
---
 .../src/svg/check_24px.svg                         |   1 +
 .../src/svg/warning_24px.svg                       |   1 +
 .../src/wallet/AddAccount/stories.tsx              |  29 --
 .../src/wallet/AddAccount/views.tsx                | 249 ----------
 .../src/wallet/DepositPage/index.ts                |   8 +-
 .../src/wallet/DepositPage/state.ts                |  27 +-
 .../src/wallet/DepositPage/stories.tsx             |  21 +
 .../src/wallet/DepositPage/test.ts                 |  10 +-
 .../src/wallet/DepositPage/views.tsx               |  98 ++--
 .../wallet/{AddAccount => ManageAccount}/index.ts  |  11 +-
 .../wallet/{AddAccount => ManageAccount}/state.ts  |  30 +-
 .../src/wallet/ManageAccount/stories.tsx           | 208 ++++++++
 .../wallet/{AddAccount => ManageAccount}/test.ts   |   0
 .../src/wallet/ManageAccount/views.tsx             | 534 +++++++++++++++++++++
 .../src/wallet/index.stories.tsx                   |   2 +
 15 files changed, 867 insertions(+), 362 deletions(-)

diff --git a/packages/taler-wallet-webextension/src/svg/check_24px.svg 
b/packages/taler-wallet-webextension/src/svg/check_24px.svg
new file mode 100644
index 000000000..522695ef3
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/svg/check_24px.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="24" viewBox="0 0 24 24" 
width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M9 16.17L4.83 12l-1.42 
1.41L9 19 21 7l-1.41-1.41z"/></svg>
\ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/svg/warning_24px.svg 
b/packages/taler-wallet-webextension/src/svg/warning_24px.svg
new file mode 100644
index 000000000..d27c4c6ec
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/svg/warning_24px.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; height="24" viewBox="0 0 24 24" 
width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M1 21h22L12 2 1 
21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>
\ No newline at end of file
diff --git 
a/packages/taler-wallet-webextension/src/wallet/AddAccount/stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/AddAccount/stories.tsx
deleted file mode 100644
index 696e424c4..000000000
--- a/packages/taler-wallet-webextension/src/wallet/AddAccount/stories.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { createExample } from "../../test-utils.js";
-import { ReadyView } from "./views.js";
-
-export default {
-  title: "example",
-};
-
-export const Ready = createExample(ReadyView, {});
diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx 
b/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx
deleted file mode 100644
index d6ab7e967..000000000
--- a/packages/taler-wallet-webextension/src/wallet/AddAccount/views.tsx
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-import { parsePaytoUri } from "@gnu-taler/taler-util";
-import { Fragment, h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { ErrorMessage } from "../../components/ErrorMessage.js";
-import { LoadingError } from "../../components/LoadingError.js";
-import { SelectList } from "../../components/SelectList.js";
-import { Input, LightText, SubTitle } from "../../components/styled/index.js";
-import { useTranslationContext } from "../../context/translation.js";
-import { Button } from "../../mui/Button.js";
-import { TextFieldHandler } from "../../mui/handlers.js";
-import { TextField } from "../../mui/TextField.js";
-import { State } from "./index.js";
-
-export function LoadingUriView({ error }: State.LoadingUriError): VNode {
-  const { i18n } = useTranslationContext();
-
-  return (
-    <LoadingError
-      title={<i18n.Translate>Could not load</i18n.Translate>}
-      error={error}
-    />
-  );
-}
-
-export function ReadyView({
-  currency,
-  error,
-  accountType,
-  alias,
-  onAccountAdded,
-  onCancel,
-  uri,
-}: State.Ready): VNode {
-  const { i18n } = useTranslationContext();
-
-  return (
-    <Fragment>
-      <section>
-        <SubTitle>
-          <i18n.Translate>Add bank account for {currency}</i18n.Translate>
-        </SubTitle>
-        <LightText>
-          <i18n.Translate>
-            Enter the URL of an exchange you trust.
-          </i18n.Translate>
-        </LightText>
-
-        {error && (
-          <ErrorMessage
-            title={<i18n.Translate>Unable add this account</i18n.Translate>}
-            description={error}
-          />
-        )}
-        <p>
-          <Input>
-            <SelectList
-              label={<i18n.Translate>Select account type</i18n.Translate>}
-              list={accountType.list}
-              name="accountType"
-              value={accountType.value}
-              onChange={accountType.onChange}
-            />
-          </Input>
-        </p>
-        {accountType.value === "" ? undefined : (
-          <Fragment>
-            <p>
-              <CustomFieldByAccountType type={accountType.value} field={uri} />
-            </p>
-            <p>
-              <TextField
-                label="Account alias"
-                variant="standard"
-                required
-                fullWidth
-                disabled={accountType.value === ""}
-                value={alias.value}
-                onChange={alias.onInput}
-              />
-            </p>
-          </Fragment>
-        )}
-      </section>
-      <footer>
-        <Button
-          variant="contained"
-          color="secondary"
-          onClick={onCancel.onClick}
-        >
-          <i18n.Translate>Cancel</i18n.Translate>
-        </Button>
-        <Button
-          variant="contained"
-          onClick={onAccountAdded.onClick}
-          disabled={!onAccountAdded.onClick}
-        >
-          <i18n.Translate>Add</i18n.Translate>
-        </Button>
-      </footer>
-    </Fragment>
-  );
-}
-
-function BitcoinAddressAccount({ field }: { field: TextFieldHandler }): VNode {
-  const { i18n } = useTranslationContext();
-  const [value, setValue] = useState<string | undefined>(undefined);
-  const errors = undefinedIfEmpty({
-    value: !value ? i18n.str`Can't be empty` : undefined,
-  });
-  return (
-    <Fragment>
-      <TextField
-        label="Bitcoin address"
-        variant="standard"
-        fullWidth
-        value={value}
-        error={value !== undefined && !!errors?.value}
-        onChange={(v) => {
-          setValue(v);
-          if (!errors) {
-            field.onInput(`payto://bitcoin/${value}`);
-          }
-        }}
-      />
-      {value !== undefined && errors?.value && (
-        <ErrorMessage title={<span>{errors?.value}</span>} />
-      )}
-    </Fragment>
-  );
-}
-
-function undefinedIfEmpty<T extends object>(obj: T): T | undefined {
-  return Object.keys(obj).some((k) => (obj as any)[k] !== undefined)
-    ? obj
-    : undefined;
-}
-
-function TalerBankAddressAccount({
-  field,
-}: {
-  field: TextFieldHandler;
-}): VNode {
-  const { i18n } = useTranslationContext();
-  const [host, setHost] = useState<string | undefined>(undefined);
-  const [account, setAccount] = useState<string | undefined>(undefined);
-  const errors = undefinedIfEmpty({
-    host: !host ? i18n.str`Can't be empty` : undefined,
-    account: !account ? i18n.str`Can't be empty` : undefined,
-  });
-  return (
-    <Fragment>
-      <TextField
-        label="Bank host"
-        variant="standard"
-        fullWidth
-        value={host}
-        error={host !== undefined && !!errors?.host}
-        onChange={(v) => {
-          setHost(v);
-          if (!errors) {
-            field.onInput(`payto://x-taler-bank/${host}/${account}`);
-          }
-        }}
-      />{" "}
-      {host !== undefined && errors?.host && (
-        <ErrorMessage title={<span>{errors?.host}</span>} />
-      )}
-      <TextField
-        label="Bank account"
-        variant="standard"
-        fullWidth
-        value={account}
-        error={account !== undefined && !!errors?.account}
-        onChange={(v) => {
-          setAccount(v || "");
-          if (!errors) {
-            field.onInput(`payto://x-taler-bank/${host}/${account}`);
-          }
-        }}
-      />{" "}
-      {account !== undefined && errors?.account && (
-        <ErrorMessage title={<span>{errors?.account}</span>} />
-      )}
-    </Fragment>
-  );
-}
-
-function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
-  const { i18n } = useTranslationContext();
-  const [value, setValue] = useState<string | undefined>(undefined);
-  const errors = undefinedIfEmpty({
-    value: !value ? i18n.str`Can't be empty` : undefined,
-  });
-  return (
-    <Fragment>
-      <TextField
-        label="IBAN number"
-        variant="standard"
-        fullWidth
-        value={value}
-        error={value !== undefined && !!errors?.value}
-        onChange={(v) => {
-          setValue(v);
-          if (!errors) {
-            field.onInput(`payto://iba/${value}`);
-          }
-        }}
-      />
-      {value !== undefined && errors?.value && (
-        <ErrorMessage title={<span>{errors?.value}</span>} />
-      )}
-    </Fragment>
-  );
-}
-
-function CustomFieldByAccountType({
-  type,
-  field,
-}: {
-  type: string;
-  field: TextFieldHandler;
-}): VNode {
-  if (type === "bitcoin") {
-    return <BitcoinAddressAccount field={field} />;
-  }
-  if (type === "x-taler-bank") {
-    return <TalerBankAddressAccount field={field} />;
-  }
-  if (type === "iban") {
-    return <IbanAddressAccount field={field} />;
-  }
-  return <Fragment />;
-}
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
index 77661fe15..85896da26 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
@@ -24,7 +24,7 @@ import {
 } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
 import { wxApi } from "../../wxApi.js";
-import { AddAccountPage } from "../AddAccount/index.js";
+import { ManageAccountPage } from "../ManageAccount/index.js";
 import { useComponentState } from "./state.js";
 import {
   AmountOrCurrencyErrorView,
@@ -62,7 +62,7 @@ export namespace State {
   }
 
   export interface AddingAccount {
-    status: "adding-account";
+    status: "manage-account";
     error: undefined;
     currency: string;
     onAccountAdded: (p: string) => void;
@@ -94,7 +94,7 @@ export namespace State {
     error: undefined;
     currency: string;
 
-    selectedAccount: PaytoUri | undefined;
+    currentAccount: PaytoUri;
     totalFee: AmountJson;
     totalToDeposit: AmountJson;
 
@@ -112,7 +112,7 @@ const viewMapping: StateViewMap<State> = {
   "amount-or-currency-error": AmountOrCurrencyErrorView,
   "no-enough-balance": NoEnoughBalanceView,
   "no-accounts": NoAccountToDepositView,
-  "adding-account": AddAccountPage,
+  "manage-account": ManageAccountPage,
   ready: ReadyView,
 };
 
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
index b3a377040..fe692e80d 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
@@ -50,9 +50,7 @@ export function useComponentState(
   // const [accountIdx, setAccountIdx] = useState<number>(0);
   const [amount, setAmount] = useState(initialValue);
 
-  const [selectedAccount, setSelectedAccount] = useState<
-    PaytoUri | undefined
-  >();
+  const [selectedAccount, setSelectedAccount] = useState<PaytoUri>();
 
   const [fee, setFee] = useState<DepositGroupFees | undefined>(undefined);
   const [addingAccount, setAddingAccount] = useState(false);
@@ -82,7 +80,7 @@ export function useComponentState(
 
   if (addingAccount) {
     return {
-      status: "adding-account",
+      status: "manage-account",
       error: undefined,
       currency,
       onAccountAdded: (p: string) => {
@@ -92,6 +90,7 @@ export function useComponentState(
       },
       onCancel: () => {
         setAddingAccount(false);
+        hook.retry();
       },
     };
   }
@@ -122,13 +121,12 @@ export function useComponentState(
       },
     };
   }
+  const firstAccount = accounts[0].uri
+  const currentAccount = !selectedAccount ? firstAccount : selectedAccount;
 
   const accountMap = createLabelsForBankAccount(accounts);
-  accountMap[""] = "Select one account...";
 
   async function updateAccountFromList(accountStr: string): Promise<void> {
-    // const newSelected = !accountMap[accountStr] ? undefined : 
accountMap[accountStr];
-    // if (!newSelected) return;
     const uri = !accountStr ? undefined : parsePaytoUri(accountStr);
     if (uri && parsedAmount) {
       try {
@@ -136,7 +134,6 @@ export function useComponentState(
         setSelectedAccount(uri);
         setFee(result);
       } catch (e) {
-        console.error(e)
         setSelectedAccount(uri);
         setFee(undefined);
       }
@@ -145,13 +142,12 @@ export function useComponentState(
 
   async function updateAmount(numStr: string): Promise<void> {
     const parsed = Amounts.parse(`${currency}:${numStr}`);
-    if (parsed && selectedAccount) {
+    if (parsed) {
       try {
-        const result = await getFeeForAmount(selectedAccount, parsed, api);
+        const result = await getFeeForAmount(currentAccount, parsed, api);
         setAmount(numStr);
         setFee(result);
       } catch (e) {
-        console.error(e)
         setAmount(numStr);
         setFee(undefined);
       }
@@ -179,15 +175,14 @@ export function useComponentState(
 
   const unableToDeposit =
     !parsedAmount || //no amount specified
-    selectedAccount === undefined || //no account selected
     Amounts.isZero(totalToDeposit) || //deposit may be zero because of fee
     fee === undefined || //no fee calculated yet
     amountError !== undefined; //amount field may be invalid
 
   async function doSend(): Promise<void> {
-    if (!selectedAccount || !parsedAmount || !currency) return;
+    if (!parsedAmount || !currency) return;
 
-    const depositPaytoUri = 
`payto://${selectedAccount.targetType}/${selectedAccount.targetPath}`;
+    const depositPaytoUri = 
`payto://${currentAccount.targetType}/${currentAccount.targetPath}`;
     const amount = Amounts.stringify(parsedAmount);
     await api.wallet.call(WalletApiOperation.CreateDepositGroup, {
       amount, depositPaytoUri
@@ -211,10 +206,10 @@ export function useComponentState(
     },
     account: {
       list: accountMap,
-      value: !selectedAccount ? "" : stringifyPaytoUri(selectedAccount),
+      value: stringifyPaytoUri(currentAccount),
       onChange: updateAccountFromList,
     },
-    selectedAccount,
+    currentAccount,
     cancelHandler: {
       onClick: async () => {
         onCancel(currency);
diff --git 
a/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx
index ed5945c06..64b2c91a7 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx
@@ -55,6 +55,13 @@ export const WithNoAccountForIBAN = createExample(ReadyView, 
{
       null;
     },
   },
+  currentAccount: {
+    isKnown: true,
+    targetType: "iban",
+    iban: "ABCD1234",
+    params: {},
+    targetPath: "/ABCD1234",
+  },
   currency: "USD",
   amount: {
     onInput: async () => {
@@ -83,6 +90,13 @@ export const WithIBANAccountTypeSelected = 
createExample(ReadyView, {
       null;
     },
   },
+  currentAccount: {
+    isKnown: true,
+    targetType: "iban",
+    iban: "ABCD1234",
+    params: {},
+    targetPath: "/ABCD1234",
+  },
   currency: "USD",
   amount: {
     onInput: async () => {
@@ -111,6 +125,13 @@ export const NewBitcoinAccountTypeSelected = 
createExample(ReadyView, {
       null;
     },
   },
+  currentAccount: {
+    isKnown: true,
+    targetType: "iban",
+    iban: "ABCD1234",
+    params: {},
+    targetPath: "/ABCD1234",
+  },
   onAddAccount: {},
   currency: "USD",
   amount: {
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
index 62097c3e4..4a648312e 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
@@ -172,7 +172,7 @@ describe("DepositPage states", () => {
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
+      expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
       expect(r.amount.value).eq("0");
       expect(r.depositHandler.onClick).undefined;
     }
@@ -195,7 +195,7 @@ describe("DepositPage states", () => {
       }],
     })
     handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
-      accounts: [ibanPayto]
+      accounts: [talerBankPayto, ibanPayto]
     });
     handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withoutFee())
     handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withoutFee())
@@ -221,7 +221,7 @@ describe("DepositPage states", () => {
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
+      expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
       expect(r.amount.value).eq("0");
       expect(r.depositHandler.onClick).undefined;
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
@@ -328,7 +328,7 @@ describe("DepositPage states", () => {
       }],
     })
     handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
-      accounts: [ibanPayto]
+      accounts: [talerBankPayto, ibanPayto]
     });
     handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withSomeFee())
     handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withSomeFee())
@@ -353,7 +353,7 @@ describe("DepositPage states", () => {
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
+      expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
       expect(r.amount.value).eq("0");
       expect(r.depositHandler.onClick).undefined;
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
diff --git 
a/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx
index ddb23c9bb..e864c8413 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx
@@ -160,61 +160,55 @@ export function ReadyView(state: State.Ready): VNode {
             variant="text"
             style={{ marginLeft: "auto" }}
           >
-            <i18n.Translate>Add another account</i18n.Translate>
+            <i18n.Translate>Manage accounts</i18n.Translate>
           </Button>
         </div>
 
-        {state.selectedAccount && (
-          <Fragment>
-            <p>
-              <AccountDetails account={state.selectedAccount} />
-            </p>
-            <InputWithLabel invalid={!!state.amount.error}>
-              <label>
-                <i18n.Translate>Amount</i18n.Translate>
-              </label>
-              <div>
-                <span>{state.currency}</span>
-                <input
-                  type="number"
-                  value={state.amount.value}
-                  onInput={(e) => state.amount.onInput(e.currentTarget.value)}
-                />
-              </div>
-              {state.amount.error && (
-                <ErrorText>{state.amount.error}</ErrorText>
-              )}
-            </InputWithLabel>
-
-            <InputWithLabel>
-              <label>
-                <i18n.Translate>Deposit fee</i18n.Translate>
-              </label>
-              <div>
-                <span>{state.currency}</span>
-                <input
-                  type="number"
-                  disabled
-                  value={Amounts.stringifyValue(state.totalFee)}
-                />
-              </div>
-            </InputWithLabel>
-
-            <InputWithLabel>
-              <label>
-                <i18n.Translate>Total deposit</i18n.Translate>
-              </label>
-              <div>
-                <span>{state.currency}</span>
-                <input
-                  type="number"
-                  disabled
-                  value={Amounts.stringifyValue(state.totalToDeposit)}
-                />
-              </div>
-            </InputWithLabel>
-          </Fragment>
-        )}
+        <p>
+          <AccountDetails account={state.currentAccount} />
+        </p>
+        <InputWithLabel invalid={!!state.amount.error}>
+          <label>
+            <i18n.Translate>Amount</i18n.Translate>
+          </label>
+          <div>
+            <span>{state.currency}</span>
+            <input
+              type="number"
+              value={state.amount.value}
+              onInput={(e) => state.amount.onInput(e.currentTarget.value)}
+            />
+          </div>
+          {state.amount.error && <ErrorText>{state.amount.error}</ErrorText>}
+        </InputWithLabel>
+
+        <InputWithLabel>
+          <label>
+            <i18n.Translate>Deposit fee</i18n.Translate>
+          </label>
+          <div>
+            <span>{state.currency}</span>
+            <input
+              type="number"
+              disabled
+              value={Amounts.stringifyValue(state.totalFee)}
+            />
+          </div>
+        </InputWithLabel>
+
+        <InputWithLabel>
+          <label>
+            <i18n.Translate>Total deposit</i18n.Translate>
+          </label>
+          <div>
+            <span>{state.currency}</span>
+            <input
+              type="number"
+              disabled
+              value={Amounts.stringifyValue(state.totalToDeposit)}
+            />
+          </div>
+        </InputWithLabel>
       </section>
       <footer>
         <Button
diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts 
b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
similarity index 86%
rename from packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts
rename to packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
index 09609a8a1..cd591be74 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
@@ -14,6 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { KnownBankAccountsInfo } from "@gnu-taler/taler-util";
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import {
@@ -57,17 +58,23 @@ export namespace State {
     alias: TextFieldHandler;
     onAccountAdded: ButtonHandler;
     onCancel: ButtonHandler;
+    accountByType: AccountByType,
+    deleteAccount: (a: KnownBankAccountsInfo) => Promise<void>,
   }
 }
 
+export type AccountByType = {
+  [key: string]: KnownBankAccountsInfo[]
+};
+
 const viewMapping: StateViewMap<State> = {
   loading: Loading,
   "loading-error": LoadingUriView,
   ready: ReadyView,
 };
 
-export const AddAccountPage = compose(
-  "AddAccount",
+export const ManageAccountPage = compose(
+  "ManageAccountPage",
   (p: Props) => useComponentState(p, wxApi),
   viewMapping,
 );
diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts 
b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
similarity index 78%
rename from packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts
rename to packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
index 6c113d732..ad8643133 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
@@ -14,12 +14,12 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util";
+import { KnownBankAccountsInfo, parsePaytoUri, stringifyPaytoUri } from 
"@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
 import { wxApi } from "../../wxApi.js";
-import { Props, State } from "./index.js";
+import { AccountByType, Props, State } from "./index.js";
 
 export function useComponentState(
   { currency, onAccountAdded, onCancel }: Props,
@@ -45,10 +45,10 @@ export function useComponentState(
   }
 
   const accountType: Record<string, string> = {
-    "": "Choose one account",
+    "": "Choose one account type",
     iban: "IBAN",
-    bitcoin: "Bitcoin",
-    "x-taler-bank": "Taler Bank",
+    // bitcoin: "Bitcoin",
+    // "x-taler-bank": "Taler Bank",
   };
   const uri = parsePaytoUri(payto);
   const found =
@@ -73,6 +73,24 @@ export function useComponentState(
 
   const unableToAdd = !type || !alias || !!paytoUriError || !uri;
 
+  const accountByType: AccountByType = {
+    iban: [],
+    bitcoin: [],
+    "x-taler-bank": [],
+  }
+
+  hook.response.accounts.forEach(acc => {
+    accountByType[acc.uri.targetType].push(acc)
+  });
+
+  async function deleteAccount(account: KnownBankAccountsInfo): Promise<void> {
+    const payto = stringifyPaytoUri(account.uri);
+    await api.wallet.call(WalletApiOperation.ForgetKnownBankAccounts, {
+      payto
+    })
+    hook?.retry()
+  }
+
   return {
     status: "ready",
     error: undefined,
@@ -97,6 +115,8 @@ export function useComponentState(
         setPayto(v);
       },
     },
+    accountByType,
+    deleteAccount,
     onAccountAdded: {
       onClick: unableToAdd ? undefined : addAccount,
     },
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ManageAccount/stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/ManageAccount/stories.tsx
new file mode 100644
index 000000000..c0d3a38b0
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/stories.tsx
@@ -0,0 +1,208 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { createExample } from "../../test-utils.js";
+import { ReadyView } from "./views.js";
+
+export default {
+  title: "wallet/manage account",
+};
+
+const nullFunction = async () => {
+  null;
+};
+
+export const JustTwoBitcoinAccounts = createExample(ReadyView, {
+  status: "ready",
+  currency: "ARS",
+  accountType: {
+    list: {
+      "": "Choose one account type",
+      iban: "IBAN",
+      // bitcoin: "Bitcoin",
+      // "x-taler-bank": "Taler Bank",
+    },
+    value: "",
+  },
+  alias: {
+    value: "",
+    onInput: nullFunction,
+  },
+  uri: {
+    value: "",
+    onInput: nullFunction,
+  },
+  accountByType: {
+    iban: [],
+    "x-taler-bank": [],
+    bitcoin: [
+      {
+        alias: "my bitcoin addr",
+        currency: "BTC",
+        kyc_completed: false,
+        uri: {
+          targetType: "bitcoin",
+          segwitAddrs: [],
+          isKnown: true,
+          targetPath: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
+          params: {},
+        },
+      },
+      {
+        alias: "my other addr",
+        currency: "BTC",
+        kyc_completed: true,
+        uri: {
+          targetType: "bitcoin",
+          segwitAddrs: [],
+          isKnown: true,
+          targetPath: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
+          params: {},
+        },
+      },
+    ],
+  },
+  onAccountAdded: {},
+  onCancel: {},
+});
+
+export const WithAllTypeOfAccounts = createExample(ReadyView, {
+  status: "ready",
+  currency: "ARS",
+  accountType: {
+    list: {
+      "": "Choose one account type",
+      iban: "IBAN",
+      // bitcoin: "Bitcoin",
+      // "x-taler-bank": "Taler Bank",
+    },
+    value: "",
+  },
+  alias: {
+    value: "",
+    onInput: nullFunction,
+  },
+  uri: {
+    value: "",
+    onInput: nullFunction,
+  },
+  accountByType: {
+    iban: [
+      {
+        alias: "my bank",
+        currency: "ARS",
+        kyc_completed: true,
+        uri: {
+          targetType: "iban",
+          iban: "ASDQWEQWE",
+          isKnown: true,
+          targetPath: "/ASDQWEQWE",
+          params: {},
+        },
+      },
+    ],
+    "x-taler-bank": [
+      {
+        alias: "my xtaler bank",
+        currency: "ARS",
+        kyc_completed: true,
+        uri: {
+          targetType: "x-taler-bank",
+          host: "localhost",
+          account: "123",
+          isKnown: true,
+          targetPath: "localhost/123",
+          params: {},
+        },
+      },
+    ],
+    bitcoin: [
+      {
+        alias: "my bitcoin addr",
+        currency: "BTC",
+        kyc_completed: false,
+        uri: {
+          targetType: "bitcoin",
+          segwitAddrs: [],
+          isKnown: true,
+          targetPath: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
+          params: {},
+        },
+      },
+      {
+        alias: "my other addr",
+        currency: "BTC",
+        kyc_completed: true,
+        uri: {
+          targetType: "bitcoin",
+          segwitAddrs: [],
+          isKnown: true,
+          targetPath: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
+          params: {},
+        },
+      },
+    ],
+  },
+  onAccountAdded: {},
+  onCancel: {},
+});
+
+export const AddingIbanAccount = createExample(ReadyView, {
+  status: "ready",
+  currency: "ARS",
+  accountType: {
+    list: {
+      "": "Choose one account type",
+      iban: "IBAN",
+      // bitcoin: "Bitcoin",
+      // "x-taler-bank": "Taler Bank",
+    },
+    value: "iban",
+  },
+  alias: {
+    value: "",
+    onInput: nullFunction,
+  },
+  uri: {
+    value: "",
+    onInput: nullFunction,
+  },
+  accountByType: {
+    iban: [
+      {
+        alias: "my bank",
+        currency: "ARS",
+        kyc_completed: true,
+        uri: {
+          targetType: "iban",
+          iban: "ASDQWEQWE",
+          isKnown: true,
+          targetPath: "/ASDQWEQWE",
+          params: {},
+        },
+      },
+    ],
+    "x-taler-bank": [],
+    bitcoin: [],
+  },
+  onAccountAdded: {},
+  onCancel: {},
+});
diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/test.ts 
b/packages/taler-wallet-webextension/src/wallet/ManageAccount/test.ts
similarity index 100%
rename from packages/taler-wallet-webextension/src/wallet/AddAccount/test.ts
rename to packages/taler-wallet-webextension/src/wallet/ManageAccount/test.ts
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ManageAccount/views.tsx 
b/packages/taler-wallet-webextension/src/wallet/ManageAccount/views.tsx
new file mode 100644
index 000000000..9bb9e5814
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/views.tsx
@@ -0,0 +1,534 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import {
+  KnownBankAccountsInfo,
+  PaytoUriBitcoin,
+  PaytoUriIBAN,
+  PaytoUriTalerBank,
+} from "@gnu-taler/taler-util";
+import { styled } from "@linaria/react";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { ErrorMessage } from "../../components/ErrorMessage.js";
+import { LoadingError } from "../../components/LoadingError.js";
+import { SelectList } from "../../components/SelectList.js";
+import {
+  Input,
+  LightText,
+  SubTitle,
+  SvgIcon,
+  WarningText,
+} from "../../components/styled/index.js";
+import { useTranslationContext } from "../../context/translation.js";
+import { Button } from "../../mui/Button.js";
+import { TextFieldHandler } from "../../mui/handlers.js";
+import { TextField } from "../../mui/TextField.js";
+import checkIcon from "../../svg/check_24px.svg";
+import warningIcon from "../../svg/warning_24px.svg";
+import deleteIcon from "../../svg/delete_24px.svg";
+import { State } from "./index.js";
+
+type AccountType = "bitcoin" | "x-taler-bank" | "iban";
+type ComponentFormByAccountType = {
+  [type in AccountType]: (props: { field: TextFieldHandler }) => VNode;
+};
+
+type ComponentListByAccountType = {
+  [type in AccountType]: (props: {
+    list: KnownBankAccountsInfo[];
+    onDelete: (a: KnownBankAccountsInfo) => Promise<void>;
+  }) => VNode;
+};
+
+const formComponentByAccountType: ComponentFormByAccountType = {
+  iban: IbanAddressAccount,
+  bitcoin: BitcoinAddressAccount,
+  "x-taler-bank": TalerBankAddressAccount,
+};
+const tableComponentByAccountType: ComponentListByAccountType = {
+  iban: IbanTable,
+  bitcoin: BitcoinTable,
+  "x-taler-bank": TalerBankTable,
+};
+
+const AccountTable = styled.table`
+  width: 100%;
+
+  border-collapse: separate;
+  border-spacing: 0px 10px;
+  tbody tr:nth-child(odd) > td:not(.actions, .kyc) {
+    background-color: lightgrey;
+  }
+  .actions,
+  .kyc {
+    width: 10px;
+    background-color: inherit;
+  }
+`;
+
+export function LoadingUriView({ error }: State.LoadingUriError): VNode {
+  const { i18n } = useTranslationContext();
+
+  return (
+    <LoadingError
+      title={<i18n.Translate>Could not load</i18n.Translate>}
+      error={error}
+    />
+  );
+}
+
+export function ReadyView({
+  currency,
+  error,
+  accountType,
+  accountByType,
+  alias,
+  onAccountAdded,
+  deleteAccount,
+  onCancel,
+  uri,
+}: State.Ready): VNode {
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <section>
+        <SubTitle>
+          <i18n.Translate>Known accounts for {currency}</i18n.Translate>
+        </SubTitle>
+        <p>
+          <i18n.Translate>
+            To add a new account first select the account type.
+          </i18n.Translate>
+        </p>
+
+        {error && (
+          <ErrorMessage
+            title={<i18n.Translate>Unable add this account</i18n.Translate>}
+            description={error}
+          />
+        )}
+        <p>
+          <Input>
+            <SelectList
+              label={<i18n.Translate>Select account type</i18n.Translate>}
+              list={accountType.list}
+              name="accountType"
+              value={accountType.value}
+              onChange={accountType.onChange}
+            />
+          </Input>
+        </p>
+        {accountType.value === "" ? undefined : (
+          <Fragment>
+            <p>
+              <CustomFieldByAccountType
+                type={accountType.value as AccountType}
+                field={uri}
+              />
+            </p>
+            <p>
+              <TextField
+                label="Account alias"
+                variant="standard"
+                required
+                fullWidth
+                disabled={accountType.value === ""}
+                value={alias.value}
+                onChange={alias.onInput}
+              />
+            </p>
+          </Fragment>
+        )}
+      </section>
+      <section>
+        <Button
+          variant="contained"
+          color="secondary"
+          onClick={onCancel.onClick}
+        >
+          <i18n.Translate>Cancel</i18n.Translate>
+        </Button>
+        <Button
+          variant="contained"
+          onClick={onAccountAdded.onClick}
+          disabled={!onAccountAdded.onClick}
+        >
+          <i18n.Translate>Add</i18n.Translate>
+        </Button>
+      </section>
+      <section>
+        {Object.entries(accountByType).map(([type, list]) => {
+          const Table = tableComponentByAccountType[type as AccountType];
+          return <Table key={type} list={list} onDelete={deleteAccount} />;
+        })}
+      </section>
+    </Fragment>
+  );
+}
+
+function IbanTable({
+  list,
+  onDelete,
+}: {
+  list: KnownBankAccountsInfo[];
+  onDelete: (ac: KnownBankAccountsInfo) => void;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  if (list.length === 0) return <Fragment />;
+  return (
+    <div>
+      <h1>
+        <i18n.Translate>IBAN accounts</i18n.Translate>
+      </h1>
+      <AccountTable>
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Alias</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Int. Account Number</i18n.Translate>
+            </th>
+            <th class="kyc">
+              <i18n.Translate>KYC</i18n.Translate>
+            </th>
+            <th class="actions"></th>
+          </tr>
+        </thead>
+        <tbody>
+          {list.map((account) => {
+            const p = account.uri as PaytoUriIBAN;
+            return (
+              <tr key={account.alias}>
+                <td>{account.alias}</td>
+                <td>{p.targetPath}</td>
+                <td class="kyc">
+                  {account.kyc_completed ? (
+                    <SvgIcon
+                      title={i18n.str`KYC done`}
+                      dangerouslySetInnerHTML={{ __html: checkIcon }}
+                      color="green"
+                    />
+                  ) : (
+                    <SvgIcon
+                      title={i18n.str`KYC missing`}
+                      dangerouslySetInnerHTML={{ __html: warningIcon }}
+                      color="orange"
+                    />
+                  )}
+                </td>
+                <td class="actions">
+                  <Button
+                    variant="outlined"
+                    startIcon={deleteIcon}
+                    size="small"
+                    onClick={async () => onDelete(account)}
+                    color="error"
+                  >
+                    Forget
+                  </Button>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </AccountTable>
+    </div>
+  );
+}
+
+function TalerBankTable({
+  list,
+  onDelete,
+}: {
+  list: KnownBankAccountsInfo[];
+  onDelete: (ac: KnownBankAccountsInfo) => void;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  if (list.length === 0) return <Fragment />;
+  return (
+    <div>
+      <h1>
+        <i18n.Translate>Taler accounts</i18n.Translate>
+      </h1>
+      <AccountTable>
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Alias</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Host</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Account</i18n.Translate>
+            </th>
+            <th class="kyc">
+              <i18n.Translate>KYC</i18n.Translate>
+            </th>
+            <th class="actions"></th>
+          </tr>
+        </thead>
+        <tbody>
+          {list.map((account) => {
+            const p = account.uri as PaytoUriTalerBank;
+            return (
+              <tr key={account.alias}>
+                <td>{account.alias}</td>
+                <td>{p.host}</td>
+                <td>{p.account}</td>
+                <td class="kyc">
+                  {account.kyc_completed ? (
+                    <SvgIcon
+                      title={i18n.str`KYC done`}
+                      dangerouslySetInnerHTML={{ __html: checkIcon }}
+                      color="green"
+                    />
+                  ) : (
+                    <SvgIcon
+                      title={i18n.str`KYC missing`}
+                      dangerouslySetInnerHTML={{ __html: warningIcon }}
+                      color="orange"
+                    />
+                  )}
+                </td>
+                <td class="actions">
+                  <Button
+                    variant="outlined"
+                    startIcon={deleteIcon}
+                    size="small"
+                    onClick={async () => onDelete(account)}
+                    color="error"
+                  >
+                    Forget
+                  </Button>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </AccountTable>
+    </div>
+  );
+}
+
+function BitcoinTable({
+  list,
+  onDelete,
+}: {
+  list: KnownBankAccountsInfo[];
+  onDelete: (ac: KnownBankAccountsInfo) => void;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  if (list.length === 0) return <Fragment />;
+  return (
+    <div>
+      <h2>
+        <i18n.Translate>Bitcoin accounts</i18n.Translate>
+      </h2>
+      <AccountTable>
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Alias</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Address</i18n.Translate>
+            </th>
+            <th class="kyc">
+              <i18n.Translate>KYC</i18n.Translate>
+            </th>
+            <th class="actions"></th>
+          </tr>
+        </thead>
+        <tbody>
+          {list.map((account) => {
+            const p = account.uri as PaytoUriBitcoin;
+            return (
+              <tr key={account.alias}>
+                <td>{account.alias}</td>
+                <td>{p.targetPath}</td>
+                <td class="kyc">
+                  {account.kyc_completed ? (
+                    <SvgIcon
+                      title={i18n.str`KYC done`}
+                      dangerouslySetInnerHTML={{ __html: checkIcon }}
+                      color="green"
+                    />
+                  ) : (
+                    <SvgIcon
+                      title={i18n.str`KYC missing`}
+                      dangerouslySetInnerHTML={{ __html: warningIcon }}
+                      color="orange"
+                    />
+                  )}
+                </td>
+                <td class="actions">
+                  <Button
+                    variant="outlined"
+                    startIcon={deleteIcon}
+                    size="small"
+                    onClick={async () => onDelete(account)}
+                    color="error"
+                  >
+                    Forget
+                  </Button>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </AccountTable>
+    </div>
+  );
+}
+
+function BitcoinAddressAccount({ field }: { field: TextFieldHandler }): VNode {
+  const { i18n } = useTranslationContext();
+  const [value, setValue] = useState<string | undefined>(undefined);
+  const errors = undefinedIfEmpty({
+    value: !value ? i18n.str`Can't be empty` : undefined,
+  });
+  return (
+    <Fragment>
+      <TextField
+        label="Bitcoin address"
+        variant="standard"
+        fullWidth
+        value={value}
+        error={value !== undefined && !!errors?.value}
+        onChange={(v) => {
+          setValue(v);
+          if (!errors) {
+            field.onInput(`payto://bitcoin/${v}`);
+          }
+        }}
+      />
+      {value !== undefined && errors?.value && (
+        <ErrorMessage title={<span>{errors?.value}</span>} />
+      )}
+    </Fragment>
+  );
+}
+
+function undefinedIfEmpty<T extends object>(obj: T): T | undefined {
+  return Object.keys(obj).some((k) => (obj as any)[k] !== undefined)
+    ? obj
+    : undefined;
+}
+
+function TalerBankAddressAccount({
+  field,
+}: {
+  field: TextFieldHandler;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  const [host, setHost] = useState<string | undefined>(undefined);
+  const [account, setAccount] = useState<string | undefined>(undefined);
+  const errors = undefinedIfEmpty({
+    host: !host ? i18n.str`Can't be empty` : undefined,
+    account: !account ? i18n.str`Can't be empty` : undefined,
+  });
+  return (
+    <Fragment>
+      <TextField
+        label="Bank host"
+        variant="standard"
+        fullWidth
+        value={host}
+        error={host !== undefined && !!errors?.host}
+        onChange={(v) => {
+          setHost(v);
+          if (!errors) {
+            field.onInput(`payto://x-taler-bank/${v}/${account}`);
+          }
+        }}
+      />{" "}
+      {host !== undefined && errors?.host && (
+        <ErrorMessage title={<span>{errors?.host}</span>} />
+      )}
+      <TextField
+        label="Bank account"
+        variant="standard"
+        fullWidth
+        value={account}
+        error={account !== undefined && !!errors?.account}
+        onChange={(v) => {
+          setAccount(v || "");
+          if (!errors) {
+            field.onInput(`payto://x-taler-bank/${host}/${v}`);
+          }
+        }}
+      />{" "}
+      {account !== undefined && errors?.account && (
+        <ErrorMessage title={<span>{errors?.account}</span>} />
+      )}
+    </Fragment>
+  );
+}
+
+function IbanAddressAccount({ field }: { field: TextFieldHandler }): VNode {
+  const { i18n } = useTranslationContext();
+  const [value, setValue] = useState<string | undefined>(undefined);
+  const errors = undefinedIfEmpty({
+    value: !value ? i18n.str`Can't be empty` : undefined,
+  });
+  return (
+    <Fragment>
+      <TextField
+        label="IBAN number"
+        variant="standard"
+        fullWidth
+        value={value}
+        error={value !== undefined && !!errors?.value}
+        onChange={(v) => {
+          setValue(v);
+          if (!errors) {
+            field.onInput(`payto://iban/${v}`);
+          }
+        }}
+      />
+      {value !== undefined && errors?.value && (
+        <ErrorMessage title={<span>{errors?.value}</span>} />
+      )}
+    </Fragment>
+  );
+}
+
+function CustomFieldByAccountType({
+  type,
+  field,
+}: {
+  type: AccountType;
+  field: TextFieldHandler;
+}): VNode {
+  const { i18n } = useTranslationContext();
+
+  const AccountForm = formComponentByAccountType[type];
+
+  return (
+    <div>
+      <WarningText>
+        <i18n.Translate>
+          We can not validate the account so make sure the value is correct.
+        </i18n.Translate>
+      </WarningText>
+      <AccountForm field={field} />
+    </div>
+  );
+}
diff --git a/packages/taler-wallet-webextension/src/wallet/index.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/index.stories.tsx
index c2f0c6481..d63f25ead 100644
--- a/packages/taler-wallet-webextension/src/wallet/index.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/index.stories.tsx
@@ -37,6 +37,7 @@ import * as a16 from "./DeveloperPage.stories.js";
 import * as a17 from "./QrReader.stories.js";
 import * as a18 from "./DestinationSelection.stories.js";
 import * as a19 from "./ExchangeSelection/stories.js";
+import * as a20 from "./ManageAccount/stories.js";
 
 export default [
   a1,
@@ -57,4 +58,5 @@ export default [
   a17,
   a18,
   a19,
+  a20,
 ];

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