gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 11/20: more ui


From: gnunet
Subject: [taler-wallet-core] 11/20: more ui
Date: Mon, 25 Sep 2023 19:51:15 +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 dfd23f63ba40a2afb0cb41bf742b0ae647a2b38c
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Sep 22 12:41:43 2023 -0300

    more ui
---
 .../demobank-ui/src/pages/OperationState/index.ts  | 117 +++++++++
 .../demobank-ui/src/pages/OperationState/state.ts  | 162 +++++++++++++
 .../src/pages/OperationState/stories.tsx           |  29 +++
 .../demobank-ui/src/pages/OperationState/test.ts   |  32 +++
 .../demobank-ui/src/pages/OperationState/views.tsx |  65 +++++
 .../demobank-ui/src/pages/admin/AccountList.tsx    | 269 +++++++++------------
 packages/demobank-ui/src/pages/admin/Home.tsx      |   4 +-
 7 files changed, 526 insertions(+), 152 deletions(-)

diff --git a/packages/demobank-ui/src/pages/OperationState/index.ts 
b/packages/demobank-ui/src/pages/OperationState/index.ts
new file mode 100644
index 000000000..254fcba5f
--- /dev/null
+++ b/packages/demobank-ui/src/pages/OperationState/index.ts
@@ -0,0 +1,117 @@
+/*
+ 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 { HttpError, HttpResponseOk, HttpResponsePaginated, utils } from 
"@gnu-taler/web-util/browser";
+import { AbsoluteTime, AmountJson, PaytoUriIBAN, PaytoUriTalerBank, 
WithdrawUriResult } from "@gnu-taler/taler-util";
+import { Loading } from "../../components/Loading.js";
+import { useComponentState } from "./state.js";
+import { ReadyView, AbortedView, ConfirmedView, InvalidPaytoView, 
InvalidReserveView, InvalidWithdrawalView, NeedConfirmationView } from 
"./views.js";
+import { VNode } from "preact";
+import { LoginForm } from "../LoginForm.js";
+import { ErrorLoading } from "../../components/ErrorLoading.js";
+
+export interface Props {
+  currency: string;
+  onClose: () => void;
+}
+
+export type State = State.Loading |
+  State.LoadingError |
+  State.Ready |
+  State.Aborted |
+  State.Confirmed |
+  State.InvalidPayto |
+  State.InvalidWithdrawal |
+  State.InvalidReserve |
+  State.NeedConfirmation;
+
+export namespace State {
+  export interface Loading {
+    status: "loading";
+    error: undefined;
+  }
+
+  export interface LoadingError {
+    status: "loading-error";
+    error: HttpError<SandboxBackend.SandboxError>;
+  }
+
+  /**
+   * Need to open the wallet
+   */
+  export interface Ready {
+    status: "ready";
+    error: undefined;
+    uri: WithdrawUriResult,
+    onClose: () => void;
+  }
+
+  export interface InvalidPayto {
+    status: "invalid-payto",
+    error: undefined;
+    payto: string | null;
+  }
+  export interface InvalidWithdrawal {
+    status: "invalid-withdrawal",
+    error: undefined;
+    uri: string,
+  }
+  export interface InvalidReserve {
+    status: "invalid-reserve",
+    error: undefined;
+    reserve: string | null;
+  }
+  export interface NeedConfirmation {
+    status: "need-confirmation",
+    error: undefined;
+  }
+  export interface Aborted {
+    status: "aborted",
+    error: undefined;
+    onClose: () => void;
+  }
+  export interface Confirmed {
+    status: "confirmed",
+    error: undefined;
+    onClose: () => void;
+  }
+
+}
+
+export interface Transaction {
+  negative: boolean;
+  counterpart: string;
+  when: AbsoluteTime;
+  amount: AmountJson | undefined;
+  subject: string;
+}
+
+const viewMapping: utils.StateViewMap<State> = {
+  loading: Loading,
+  "invalid-payto": InvalidPaytoView,
+  "invalid-withdrawal": InvalidWithdrawalView,
+  "invalid-reserve": InvalidReserveView,
+  "need-confirmation": NeedConfirmationView,
+  "aborted": AbortedView,
+  "confirmed": ConfirmedView,
+  "loading-error": ErrorLoading,
+  ready: ReadyView,
+};
+
+export const AccountPage = utils.compose(
+  (p: Props) => useComponentState(p),
+  viewMapping,
+);
diff --git a/packages/demobank-ui/src/pages/OperationState/state.ts 
b/packages/demobank-ui/src/pages/OperationState/state.ts
new file mode 100644
index 000000000..6fb7bb28f
--- /dev/null
+++ b/packages/demobank-ui/src/pages/OperationState/state.ts
@@ -0,0 +1,162 @@
+/*
+ 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 { Amounts, HttpStatusCode, TranslatedString, parsePaytoUri, 
parseWithdrawUri, stringifyWithdrawUri } from "@gnu-taler/taler-util";
+import { ErrorType, RequestError, notify, notifyError, useTranslationContext, 
utils } from "@gnu-taler/web-util/browser";
+import { useBackendContext } from "../../context/backend.js";
+import { useAccessAPI, useAccountDetails, useWithdrawalDetails } from 
"../../hooks/access.js";
+import { Props, State } from "./index.js";
+import { useSettings } from "../../hooks/settings.js";
+import { buildRequestErrorMessage } from "../../utils.js";
+import { useEffect } from "preact/hooks";
+import { getInitialBackendBaseURL } from "../../hooks/backend.js";
+
+export function useComponentState({ currency, onClose }: Props): 
utils.RecursiveState<State> {
+  const { i18n } = useTranslationContext();
+  const [settings, updateSettings] = useSettings()
+  const { createWithdrawal } = useAccessAPI();
+
+  const amount = settings.maxWithdrawalAmount
+  async function doSilentStart() {
+    //FIXME: if amount is not enough use balance
+    const parsedAmount = Amounts.parseOrThrow(`${currency}:${amount}`)
+
+    try {
+      const result = await createWithdrawal({
+        amount: Amounts.stringify(parsedAmount),
+      });
+      const uri = parseWithdrawUri(result.data.taler_withdraw_uri);
+      if (!uri) {
+        return notifyError(
+          i18n.str`Server responded with an invalid withdraw URI`,
+          i18n.str`Withdraw URI: ${result.data.taler_withdraw_uri}`);
+      } else {
+        updateSettings("currentWithdrawalOperationId", 
uri.withdrawalOperationId)
+      }
+    } catch (error) {
+      if (error instanceof RequestError) {
+        notify(
+          buildRequestErrorMessage(i18n, error.cause, {
+            onClientError: (status) =>
+              status === HttpStatusCode.Forbidden
+                ? i18n.str`The operation was rejected due to insufficient 
funds`
+                : undefined,
+          }),
+        );
+      } else {
+        notifyError(
+          i18n.str`Operation failed, please report`,
+          (error instanceof Error
+            ? error.message
+            : JSON.stringify(error)) as TranslatedString
+        )
+      }
+    }
+  }
+
+  useEffect(() => {
+    doSilentStart()
+  }, [settings.fastWithdrawal, amount])
+
+  const baseUrl = getInitialBackendBaseURL()
+  const withdrawalOperationId = settings.currentWithdrawalOperationId
+
+  if (!withdrawalOperationId) {
+    return {
+      status: "loading",
+      error: undefined
+    }
+  }
+
+  const bankIntegrationApiBaseUrl = `${baseUrl}/integration-api`
+  const uri = stringifyWithdrawUri({
+    bankIntegrationApiBaseUrl,
+    withdrawalOperationId,
+  });
+  const parsedUri = parseWithdrawUri(uri);
+  if (!parsedUri) {
+    return {
+      status: "invalid-withdrawal",
+      error: undefined,
+      uri,
+    }
+  }
+
+  return (): utils.RecursiveState<State> => {
+    const result = useWithdrawalDetails(withdrawalOperationId);
+    if (!result.ok) {
+      if (result.loading) {
+        return {
+          status: "loading",
+          error: undefined
+        }
+      }
+      return {
+        status: "loading-error",
+        error: result
+      }
+    }
+    const { data } = result;
+    if (data.aborted) {
+      return {
+        status: "aborted",
+        error: undefined,
+        onClose,
+      }
+    }
+
+    if (data.confirmation_done) {
+      return {
+        status: "confirmed",
+        error: undefined,
+        onClose,
+      }
+    }
+
+    if (!data.selection_done) {
+      return {
+        status: "ready",
+        error: undefined,
+        uri: parsedUri,
+        onClose
+      }
+    }
+
+    if (!data.selected_reserve_pub) {
+      return {
+        status: "invalid-reserve",
+        error: undefined,
+        reserve: data.selected_reserve_pub
+      }
+    }
+
+    const account = !data.selected_exchange_account ? undefined : 
parsePaytoUri(data.selected_exchange_account)
+
+    if (!account) {
+      return {
+        status: "invalid-payto",
+        error: undefined,
+        payto: data.selected_exchange_account
+      }
+    }
+
+    return {
+      status: "need-confirmation",
+      error: undefined,
+    }
+  }
+
+}
diff --git a/packages/demobank-ui/src/pages/OperationState/stories.tsx 
b/packages/demobank-ui/src/pages/OperationState/stories.tsx
new file mode 100644
index 000000000..03917a8fb
--- /dev/null
+++ b/packages/demobank-ui/src/pages/OperationState/stories.tsx
@@ -0,0 +1,29 @@
+/*
+ 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 * as tests from "@gnu-taler/web-util/testing";
+import { ReadyView } from "./views.js";
+
+export default {
+  title: "operation status page",
+};
+
+export const Ready = tests.createExample(ReadyView, {});
diff --git a/packages/demobank-ui/src/pages/OperationState/test.ts 
b/packages/demobank-ui/src/pages/OperationState/test.ts
new file mode 100644
index 000000000..f4d6cf4b2
--- /dev/null
+++ b/packages/demobank-ui/src/pages/OperationState/test.ts
@@ -0,0 +1,32 @@
+/*
+ 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 * as tests from "@gnu-taler/web-util/testing";
+import { SwrMockEnvironment } from "@gnu-taler/web-util/testing";
+import { expect } from "chai";
+import { CASHOUT_API_EXAMPLE } from "../../endpoints.js";
+import { Props } from "./index.js";
+import { useComponentState } from "./state.js";
+
+describe("Withdrawal operation states", () => {
+  it("should do some tests", async () => {
+  });
+});
diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx 
b/packages/demobank-ui/src/pages/OperationState/views.tsx
new file mode 100644
index 000000000..db25eaf61
--- /dev/null
+++ b/packages/demobank-ui/src/pages/OperationState/views.tsx
@@ -0,0 +1,65 @@
+/*
+ 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 { Amounts, stringifyPaytoUri } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { Transactions } from "../../components/Transactions/index.js";
+import { PaymentOptions } from "../PaymentOptions.js";
+import { State } from "./index.js";
+import { CopyButton } from "../../components/CopyButton.js";
+import { bankUiSettings } from "../../settings.js";
+import { useBusinessAccountDetails } from "../../hooks/circuit.js";
+import { useSettings } from "../../hooks/settings.js";
+
+export function InvalidPaytoView({ error }: State.InvalidPayto) {
+  return (
+    <div>Payto from server is not valid &quot;{error.data.paytoUri}&quot;</div>
+  );
+}
+export function InvalidWithdrawalView({ error }: State.InvalidWithdrawal) {
+  return (
+    <div>Payto from server is not valid &quot;{error.data.paytoUri}&quot;</div>
+  );
+}
+export function InvalidReserveView({ error }: State.InvalidReserve) {
+  return (
+    <div>Payto from server is not valid &quot;{error.data.paytoUri}&quot;</div>
+  );
+}
+
+export function NeedConfirmationView({ error }: State.NeedConfirmation) {
+  return (
+    <div>Payto from server is not valid &quot;{error.data.paytoUri}&quot;</div>
+  );
+}
+export function AbortedView({ error }: State.Aborted) {
+  return (
+    <div>Payto from server is not valid &quot;{error.data.paytoUri}&quot;</div>
+  );
+}
+export function ConfirmedView({ error }: State.Confirmed) {
+  return (
+    <div>Payto from server is not valid &quot;{error.data.paytoUri}&quot;</div>
+  );
+}
+
+export function ReadyView({ account, limit, goToBusinessAccount }: 
State.Ready): VNode<{}> {
+  const { i18n } = useTranslationContext();
+
+  return <div />
+
+}
diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx 
b/packages/demobank-ui/src/pages/admin/AccountList.tsx
index 56d9c45f9..eb5765533 100644
--- a/packages/demobank-ui/src/pages/admin/AccountList.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx
@@ -6,163 +6,132 @@ import { Amounts } from "@gnu-taler/taler-util";
 import { useTranslationContext } from "@gnu-taler/web-util/browser";
 
 interface Props {
-    onAction: (type: AccountAction, account: string) => void;
-    account: string | undefined;
-    onRegister: () => void;
-    onCreateAccount: () => void;
+  onAction: (type: AccountAction, account: string) => void;
+  account: string | undefined;
+  onRegister: () => void;
+  onCreateAccount: () => void;
 }
 
 export function AccountList({ account, onAction, onCreateAccount, onRegister 
}: Props): VNode {
-    const result = useBusinessAccounts({ account });
-    const { i18n } = useTranslationContext();
+  const result = useBusinessAccounts({ account });
+  const { i18n } = useTranslationContext();
 
-    if (result.loading) return <div />;
-    if (!result.ok) {
-        return handleNotOkResult(i18n, onRegister)(result);
-    }
+  if (result.loading) return <div />;
+  if (!result.ok) {
+    return handleNotOkResult(i18n, onRegister)(result);
+  }
 
-    const { customers } = result.data;
-    return <div class="px-4 sm:px-6 lg:px-8">
-        <div class="sm:flex sm:items-center">
-            <div class="sm:flex-auto">
-                <h1 class="text-base font-semibold leading-6 text-gray-900">
-                    <i18n.Translate>Accounts</i18n.Translate>
-                </h1>
-                <p class="mt-2 text-sm text-gray-700">
-                    <i18n.Translate>A list of all business account in the 
bank.</i18n.Translate>
-                </p>
-            </div>
-            <div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
-                <button type="button" class="block rounded-md bg-indigo-600 
px-3 py-2 text-center text-sm font-semibold text-white shadow-sm 
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
-                    onClick={(e) => {
-                        e.preventDefault()
-                        onCreateAccount()
-                    }}>
-                    <i18n.Translate>Create account</i18n.Translate>
-                </button>
-            </div>
-        </div>
-        <div class="mt-8 flow-root">
-            <div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
-                <div class="inline-block min-w-full py-2 align-middle sm:px-6 
lg:px-8">
-                    {!customers.length ? (
-                        <div></div>
-                    ) : (
-                        <table class="min-w-full divide-y divide-gray-300">
-                            <thead>
-                                <tr>
-                                    <th scope="col" class="py-3.5 pl-4 pr-3 
text-left text-sm font-semibold text-gray-900 sm:pl-0">{i18n.str`Username`}</th>
-                                    <th scope="col" class="px-3 py-3.5 
text-left text-sm font-semibold text-gray-900">{i18n.str`Name`}</th>
-                                    <th scope="col" class="px-3 py-3.5 
text-left text-sm font-semibold text-gray-900">{i18n.str`Balance`}</th>
-                                    <th scope="col" class="relative py-3.5 
pl-3 pr-4 sm:pr-0">
-                                        <span 
class="sr-only">{i18n.str`Actions`}</span>
-                                    </th>
-                                </tr>
-                            </thead>
-                            <tbody class="divide-y divide-gray-200">
-                                {customers.map((item, idx) => {
-                                    const balance = !item.balance
-                                        ? undefined
-                                        : Amounts.parse(item.balance.amount);
-                                    const balanceIsDebit =
-                                        item.balance &&
-                                        item.balance.credit_debit_indicator == 
"debit";
+  const { customers } = result.data;
+  return <div class="px-4 sm:px-6 lg:px-8">
+    <div class="sm:flex sm:items-center">
+      <div class="sm:flex-auto">
+        <h1 class="text-base font-semibold leading-6 text-gray-900">
+          <i18n.Translate>Accounts</i18n.Translate>
+        </h1>
+        <p class="mt-2 text-sm text-gray-700">
+          <i18n.Translate>A list of all business account in the 
bank.</i18n.Translate>
+        </p>
+      </div>
+      <div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
+        <button type="button" class="block rounded-md bg-indigo-600 px-3 py-2 
text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 
focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 
focus-visible:outline-indigo-600"
+          onClick={(e) => {
+            e.preventDefault()
+            onCreateAccount()
+          }}>
+          <i18n.Translate>Create account</i18n.Translate>
+        </button>
+      </div>
+    </div>
+    <div class="mt-8 flow-root">
+      <div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
+        <div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
+          {!customers.length ? (
+            <div></div>
+          ) : (
+            <table class="min-w-full divide-y divide-gray-300">
+              <thead>
+                <tr>
+                  <th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm 
font-semibold text-gray-900 sm:pl-0">{i18n.str`Username`}</th>
+                  <th scope="col" class="px-3 py-3.5 text-left text-sm 
font-semibold text-gray-900">{i18n.str`Name`}</th>
+                  <th scope="col" class="px-3 py-3.5 text-left text-sm 
font-semibold text-gray-900">{i18n.str`Balance`}</th>
+                  <th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-0">
+                    <span class="sr-only">{i18n.str`Actions`}</span>
+                  </th>
+                </tr>
+              </thead>
+              <tbody class="divide-y divide-gray-200">
+                {customers.map((item, idx) => {
+                  const balance = !item.balance
+                    ? undefined
+                    : Amounts.parse(item.balance.amount);
+                  const balanceIsDebit =
+                    item.balance &&
+                    item.balance.credit_debit_indicator == "debit";
 
-                                    return <tr key={idx}>
-                                        <td class="whitespace-nowrap py-4 pl-4 
pr-3 text-sm font-medium text-gray-900 sm:pl-0">
-                                            {item.username}
-                                        </td>
-                                        <td class="whitespace-nowrap px-3 py-4 
text-sm text-gray-500">
-                                            {item.name}
-                                        </td>
-                                        <td class="whitespace-nowrap px-3 py-4 
text-sm text-gray-500">
-                                            {!balance ? (
-                                                i18n.str`unknown`
-                                            ) : (
-                                                <span class="amount">
-                                                    {balanceIsDebit ? <b>-</b> 
: null}
-                                                    <span 
class="value">{`${Amounts.stringifyValue(
-                                                        balance,
-                                                    )}`}</span>
-                                                    &nbsp;
-                                                    <span 
class="currency">{`${balance.currency}`}</span>
-                                                </span>
-                                            )}
-                                        </td>
-                                        <td class="relative whitespace-nowrap 
py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-0">
-                                            <a href="#" class="text-indigo-600 
hover:text-indigo-900"
-                                                onClick={(e) => {
-                                                    e.preventDefault();
-                                                    
onAction("update-password", item.username)
-                                                }}
-                                            >
-                                                change password
-                                            </a>
-                                            <br/>
-                                            <a href="#" class="text-indigo-600 
hover:text-indigo-900" onClick={(e) => {
-                                                e.preventDefault();
-                                                onAction("show-cashout", 
item.username)
-                                            }}
-                                            >
-                                                cashouts
-                                            </a>
-                                            <br/>
-                                            <a href="#" class="text-indigo-600 
hover:text-indigo-900" onClick={(e) => {
-                                                e.preventDefault();
-                                                onAction("remove-account", 
item.username)
-                                            }}
-                                            >
-                                                remove
-                                            </a>
-                                        </td>
-                                    </tr>
-                                })}
+                  return <tr key={idx}>
+                    <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm 
font-medium text-gray-900 sm:pl-0">
+                      <a href="#" class="text-indigo-600 hover:text-indigo-900"
+                        onClick={(e) => {
+                          e.preventDefault();
+                          onAction("show-details", item.username)
+                        }}
+                      >
+                        {item.username}
+                      </a>
 
-                                {/* <!-- More people... --> */}
-                            </tbody>
-                        </table>
-                    )}
-                </div>
-            </div>
-        </div>
-    </div>
 
-    //     return <section
-    //         id="main"
-    //         style={{ width: 600, marginLeft: "auto", marginRight: "auto" }}
-    //     >
-    //             <article>
-    //                 <h2>{i18n.str`Accounts:`}</h2>
-    //                 <div class="results">
-    //                     <table class="pure-table pure-table-striped">
-    //                         <tbody>
-    //                                 return (
-    //                                     <tr key={idx}>
-    //                                         <td>
-    //                                             <a
-    //                                                 href="#"
-    //                                                 onClick={(e) => {
-    //                                                     e.preventDefault();
-    //                                                     
onAction("show-details", item.username)
-    //                                                 }}
-    //                                             >
-    // {item.username}
-    //                                             </a>
-    //                                         </td>
-    //                                         <td>{item.name}</td>
-    //                                         <td>
-    //                                             
-    //                                         </td>
-    //                                         <td>
+                    </td>
+                    <td class="whitespace-nowrap px-3 py-4 text-sm 
text-gray-500">
+                      {item.name}
+                    </td>
+                    <td class="whitespace-nowrap px-3 py-4 text-sm 
text-gray-500">
+                      {!balance ? (
+                        i18n.str`unknown`
+                      ) : (
+                        <span class="amount">
+                          {balanceIsDebit ? <b>-</b> : null}
+                          <span class="value">{`${Amounts.stringifyValue(
+                            balance,
+                          )}`}</span>
+                          &nbsp;
+                          <span class="currency">{`${balance.currency}`}</span>
+                        </span>
+                      )}
+                    </td>
+                    <td class="relative whitespace-nowrap py-4 pl-3 pr-4 
text-right text-sm font-medium sm:pr-0">
+                      <a href="#" class="text-indigo-600 hover:text-indigo-900"
+                        onClick={(e) => {
+                          e.preventDefault();
+                          onAction("update-password", item.username)
+                        }}
+                      >
+                        change password
+                      </a>
+                      <br />
+                      <a href="#" class="text-indigo-600 
hover:text-indigo-900" onClick={(e) => {
+                        e.preventDefault();
+                        onAction("show-cashout", item.username)
+                      }}
+                      >
+                        cashouts
+                      </a>
+                      <br />
+                      <a href="#" class="text-indigo-600 
hover:text-indigo-900" onClick={(e) => {
+                        e.preventDefault();
+                        onAction("remove-account", item.username)
+                      }}
+                      >
+                        remove
+                      </a>
+                    </td>
+                  </tr>
+                })}
 
-    //                                         </td>
-    //                                     </tr>
-    //                                 );
-    //                             })}
-    //                         </tbody>
-    //                     </table>
-    //                 </div>
-    //             </article>
-    //         )}
-    //     </section>
+              </tbody>
+            </table>
+          )}
+        </div>
+      </div>
+    </div>
+  </div>
 }
\ No newline at end of file
diff --git a/packages/demobank-ui/src/pages/admin/Home.tsx 
b/packages/demobank-ui/src/pages/admin/Home.tsx
index 625a49d45..5033b7fdc 100644
--- a/packages/demobank-ui/src/pages/admin/Home.tsx
+++ b/packages/demobank-ui/src/pages/admin/Home.tsx
@@ -35,7 +35,7 @@ export function AdminHome({ onRegister }: Props): VNode {
 
   if (action) {
     switch (action.type) {
-      case "show-details": return <ShowCashoutDetails
+      case "show-cashouts-details": return <ShowCashoutDetails
         id={action.account}
         onLoadNotOk={handleNotOkResult(i18n, onRegister)}
         onCancel={() => {
@@ -93,7 +93,7 @@ export function AdminHome({ onRegister }: Props): VNode {
           setAction(undefined);
         }}
       />
-      case "show-cashouts-details": return <ShowAccountDetails
+      case "show-details": return <ShowAccountDetails
         account={action.account}
         onLoadNotOk={handleNotOkResult(i18n, onRegister)}
         onChangePassword={() => {

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