gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (285d28764 -> f68585db5)


From: gnunet
Subject: [taler-wallet-core] branch master updated (285d28764 -> f68585db5)
Date: Mon, 05 Feb 2024 18:59:09 +0100

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

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

    from 285d28764 fix rollback
     new 58d45fc8a some fixes from the last QC meeting
     new f68585db5 pretty

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 packages/demobank-ui/src/Routing.tsx               | 88 ++++++++++++++++------
 .../src/components/Transactions/state.ts           | 54 ++++++-------
 .../src/components/Transactions/views.tsx          |  6 +-
 packages/demobank-ui/src/context/config.ts         |  2 +-
 packages/demobank-ui/src/context/navigation.ts     | 39 ++++++----
 .../demobank-ui/src/context/wallet-integration.ts  | 43 +++++------
 packages/demobank-ui/src/index.html                | 42 +++++------
 packages/demobank-ui/src/pages/BankFrame.tsx       | 21 +++++-
 packages/demobank-ui/src/pages/DownloadStats.tsx   |  8 +-
 packages/demobank-ui/src/pages/LoginForm.tsx       |  8 +-
 .../demobank-ui/src/pages/OperationState/views.tsx |  4 +-
 packages/demobank-ui/src/pages/PaymentOptions.tsx  | 54 ++++++++-----
 .../src/pages/PaytoWireTransferForm.tsx            | 34 ++++-----
 .../demobank-ui/src/pages/ProfileNavigation.tsx    |  2 +-
 packages/demobank-ui/src/pages/QrCodeSection.tsx   |  6 +-
 .../demobank-ui/src/pages/RegistrationPage.tsx     | 16 ++--
 .../demobank-ui/src/pages/SolveChallengePage.tsx   | 59 ++++++++++-----
 .../demobank-ui/src/pages/WalletWithdrawForm.tsx   | 22 +++---
 .../demobank-ui/src/pages/WithdrawalQRCode.tsx     | 13 +++-
 .../src/pages/account/ShowAccountDetails.tsx       | 14 ++--
 .../src/pages/account/UpdateAccountPassword.tsx    | 12 +--
 .../demobank-ui/src/pages/admin/AccountForm.tsx    | 87 +++++++++------------
 .../demobank-ui/src/pages/admin/AccountList.tsx    |  8 +-
 packages/demobank-ui/src/pages/admin/AdminHome.tsx | 10 +--
 .../demobank-ui/src/pages/admin/RemoveAccount.tsx  |  6 +-
 .../src/pages/business/CreateCashout.tsx           | 33 ++++----
 .../src/pages/business/ShowCashoutDetails.tsx      |  2 +-
 packages/demobank-ui/src/route.ts                  |  6 +-
 packages/demobank-ui/src/utils.ts                  |  3 +-
 29 files changed, 401 insertions(+), 301 deletions(-)

diff --git a/packages/demobank-ui/src/Routing.tsx 
b/packages/demobank-ui/src/Routing.tsx
index afc13636a..409d4ec2d 100644
--- a/packages/demobank-ui/src/Routing.tsx
+++ b/packages/demobank-ui/src/Routing.tsx
@@ -92,15 +92,15 @@ function PublicRounting({
   const settings = useSettingsContext();
   const { i18n } = useTranslationContext();
   const location = useCurrentLocation(publicPages);
-  const { navigateTo } = useNavigationContext()
+  const { navigateTo } = useNavigationContext();
   const { api } = useBankCoreApiContext();
   const [notification, notify, handleError] = useLocalNotification();
 
   useEffect(() => {
     if (location === undefined) {
-      navigateTo(publicPages.login.url({}))
+      navigateTo(publicPages.login.url({}));
     }
-  }, [location])
+  }, [location]);
 
   if (location === undefined) {
     return <Fragment />;
@@ -166,7 +166,9 @@ function PublicRounting({
           operationId={wopid}
           onOperationAborted={() => navigateTo(publicPages.login.url({}))}
           routeClose={publicPages.login}
-          onAuthorizationRequired={() => 
navigateTo(publicPages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(publicPages.solveSecondFactor.url({}))
+          }
         />
       );
     }
@@ -253,13 +255,13 @@ function PrivateRouting({
   username: string;
   isAdmin: boolean;
 }): VNode {
-  const { navigateTo } = useNavigationContext()
+  const { navigateTo } = useNavigationContext();
   const location = useCurrentLocation(privatePages);
   useEffect(() => {
     if (location === undefined) {
-      navigateTo(privatePages.home.url({}))
+      navigateTo(privatePages.home.url({}));
     }
-  }, [location])
+  }, [location]);
 
   if (location === undefined) {
     return <Fragment />;
@@ -277,7 +279,9 @@ function PrivateRouting({
           operationId={wopid}
           onOperationAborted={() => navigateTo(privatePages.home.url({}))}
           routeClose={privatePages.home}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
         />
       );
     }
@@ -312,7 +316,9 @@ function PrivateRouting({
         <ShowAccountDetails
           account={account}
           onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeClose={privatePages.home}
         />
       );
@@ -327,7 +333,9 @@ function PrivateRouting({
           focus
           account={account}
           onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeClose={privatePages.home}
         />
       );
@@ -341,7 +349,9 @@ function PrivateRouting({
         <RemoveAccount
           account={account}
           onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeCancel={privatePages.home}
         />
       );
@@ -356,7 +366,9 @@ function PrivateRouting({
           account={account}
           routeCashoutDetails={privatePages.cashoutDetails}
           routeClose={privatePages.home}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
         />
       );
     }
@@ -365,7 +377,9 @@ function PrivateRouting({
         <RemoveAccount
           account={username}
           onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeCancel={privatePages.home}
         />
       );
@@ -375,7 +389,9 @@ function PrivateRouting({
         <ShowAccountDetails
           account={username}
           onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeClose={privatePages.home}
         />
       );
@@ -386,7 +402,9 @@ function PrivateRouting({
           focus
           account={username}
           onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeClose={privatePages.home}
         />
       );
@@ -396,7 +414,9 @@ function PrivateRouting({
         <CashoutListForAccount
           account={username}
           routeCashoutDetails={privatePages.cashoutDetails}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeClose={privatePages.home}
         />
       );
@@ -405,7 +425,9 @@ function PrivateRouting({
       if (isAdmin) {
         return (
           <AdminHome
-            onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+            onAuthorizationRequired={() =>
+              navigateTo(privatePages.solveSecondFactor.url({}))
+            }
             routeCreate={privatePages.accountCreate}
             routeRemoveAccount={privatePages.accountDelete}
             routeShowAccount={privatePages.accountDetails}
@@ -422,8 +444,12 @@ function PrivateRouting({
           routeWireTransfer={privatePages.homeWireTransfer}
           routeClose={privatePages.home}
           onClose={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
-          onOperationCreated={(wopid) => 
navigateTo(privatePages.operationDetails.url({ wopid }))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
+          onOperationCreated={(wopid) =>
+            navigateTo(privatePages.operationDetails.url({ wopid }))
+          }
         />
       );
     }
@@ -431,7 +457,9 @@ function PrivateRouting({
       return (
         <CreateCashout
           account={username}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeClose={privatePages.home}
         />
       );
@@ -456,7 +484,9 @@ function PrivateRouting({
       return (
         <WireTransfer
           toAccount={destination}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
           routeCancel={privatePages.home}
           onSuccess={() => navigateTo(privatePages.home.url({}))}
         />
@@ -471,8 +501,12 @@ function PrivateRouting({
           routeWireTransfer={privatePages.homeWireTransfer}
           routeClose={privatePages.home}
           onClose={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
-          onOperationCreated={(wopid) => 
navigateTo(privatePages.operationDetails.url({ wopid }))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
+          onOperationCreated={(wopid) =>
+            navigateTo(privatePages.operationDetails.url({ wopid }))
+          }
         />
       );
     }
@@ -485,8 +519,12 @@ function PrivateRouting({
           routeWireTransfer={privatePages.homeWireTransfer}
           routeClose={privatePages.home}
           onClose={() => navigateTo(privatePages.home.url({}))}
-          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
-          onOperationCreated={(wopid) => 
navigateTo(privatePages.operationDetails.url({ wopid }))}
+          onAuthorizationRequired={() =>
+            navigateTo(privatePages.solveSecondFactor.url({}))
+          }
+          onOperationCreated={(wopid) =>
+            navigateTo(privatePages.operationDetails.url({ wopid }))
+          }
         />
       );
     }
diff --git a/packages/demobank-ui/src/components/Transactions/state.ts 
b/packages/demobank-ui/src/components/Transactions/state.ts
index 4109c88b2..74e6b0d36 100644
--- a/packages/demobank-ui/src/components/Transactions/state.ts
+++ b/packages/demobank-ui/src/components/Transactions/state.ts
@@ -42,34 +42,34 @@ export function useComponentState({ account }: Props): 
State {
     result.data.type === "fail"
       ? []
       : result.data.body.transactions
-        .map((tx) => {
-          const negative = tx.direction === "debit";
-          const cp = parsePaytoUri(
-            negative ? tx.creditor_payto_uri : tx.debtor_payto_uri,
-          );
-          const counterpart =
-            (cp === undefined || !cp.isKnown
-              ? undefined
-              : cp.targetType === "iban"
-                ? cp.iban
-                : cp.targetType === "x-taler-bank"
-                  ? cp.account
-                  : cp.targetType === "bitcoin"
-                    ? `${cp.targetPath.substring(0, 6)}...`
-                    : undefined) ?? "unknown";
+          .map((tx) => {
+            const negative = tx.direction === "debit";
+            const cp = parsePaytoUri(
+              negative ? tx.creditor_payto_uri : tx.debtor_payto_uri,
+            );
+            const counterpart =
+              (cp === undefined || !cp.isKnown
+                ? undefined
+                : cp.targetType === "iban"
+                  ? cp.iban
+                  : cp.targetType === "x-taler-bank"
+                    ? cp.account
+                    : cp.targetType === "bitcoin"
+                      ? `${cp.targetPath.substring(0, 6)}...`
+                      : undefined) ?? "unknown";
 
-          const when = AbsoluteTime.fromProtocolTimestamp(tx.date);
-          const amount = Amounts.parse(tx.amount);
-          const subject = tx.subject;
-          return {
-            negative,
-            counterpart,
-            when,
-            amount,
-            subject,
-          };
-        })
-        .filter((x): x is Transaction => x !== undefined);
+            const when = AbsoluteTime.fromProtocolTimestamp(tx.date);
+            const amount = Amounts.parse(tx.amount);
+            const subject = tx.subject;
+            return {
+              negative,
+              counterpart,
+              when,
+              amount,
+              subject,
+            };
+          })
+          .filter((x): x is Transaction => x !== undefined);
 
   return {
     status: "ready",
diff --git a/packages/demobank-ui/src/components/Transactions/views.tsx 
b/packages/demobank-ui/src/components/Transactions/views.tsx
index 1d63cc2cb..51fb90b61 100644
--- a/packages/demobank-ui/src/components/Transactions/views.tsx
+++ b/packages/demobank-ui/src/components/Transactions/views.tsx
@@ -49,7 +49,7 @@ export function ReadyView({
       <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>Latest transactions</i18n.Translate>
+            <i18n.Translate>Transactions history</i18n.Translate>
           </h1>
         </div>
       </div>
@@ -124,7 +124,7 @@ export function ReadyView({
                                 </span>
                               ) : (
                                 <span style={{ color: "grey" }}>
-                                  &lt;{i18n.str`invalid value`}&gt;
+                                  &lt;{i18n.str`Invalid value`}&gt;
                                 </span>
                               )}
                             </dd>
@@ -163,7 +163,7 @@ export function ReadyView({
                             />
                           ) : (
                             <span style={{ color: "grey" }}>
-                              &lt;{i18n.str`invalid value`}&gt;
+                              &lt;{i18n.str`Invalid value`}&gt;
                             </span>
                           )}
                         </td>
diff --git a/packages/demobank-ui/src/context/config.ts 
b/packages/demobank-ui/src/context/config.ts
index f2e37a15f..5d8a5c73f 100644
--- a/packages/demobank-ui/src/context/config.ts
+++ b/packages/demobank-ui/src/context/config.ts
@@ -134,7 +134,7 @@ export const BankCoreApiProvider = ({
       children: h(
         "div",
         {},
-        i18n.str`the bank backend is not supported. supported version 
"${checked.supported}", server version "${checked.result.version}"`,
+        i18n.str`The bank backend is not supported. Supported version 
"${checked.supported}", server version "${checked.result.version}"`,
       ),
     });
   }
diff --git a/packages/demobank-ui/src/context/navigation.ts 
b/packages/demobank-ui/src/context/navigation.ts
index fc1460c02..acdac4364 100644
--- a/packages/demobank-ui/src/context/navigation.ts
+++ b/packages/demobank-ui/src/context/navigation.ts
@@ -35,17 +35,19 @@ const Context = createContext<Type>(undefined);
 export const useNavigationContext = (): Type => useContext(Context);
 
 function getPathAndParamsFromWindow() {
-  const path = typeof window !== "undefined" ? 
window.location.hash.substring(1) : "/";
-  const params: Record<string, string> = {}
+  const path =
+    typeof window !== "undefined" ? window.location.hash.substring(1) : "/";
+  const params: Record<string, string> = {};
   if (typeof window !== "undefined") {
     for (const [key, value] of new URLSearchParams(window.location.search)) {
       params[key] = value;
     }
   }
-  return { path, params }
+  return { path, params };
 }
 
-const { path: initialPath, params: initialParams } = 
getPathAndParamsFromWindow()
+const { path: initialPath, params: initialParams } =
+  getPathAndParamsFromWindow();
 
 // there is a posibility that if the browser does a redirection
 // (which doesn't go through navigatTo function) and that exectued
@@ -53,26 +55,35 @@ const { path: initialPath, params: initialParams } = 
getPathAndParamsFromWindow(
 // into account
 const PopStateEventType = "popstate";
 
-export const BrowserHashNavigationProvider = ({ children }: { children: 
ComponentChildren }): VNode => {
-  const [{ path, params }, setState] = useState({ path: initialPath, params: 
initialParams })
+export const BrowserHashNavigationProvider = ({
+  children,
+}: {
+  children: ComponentChildren;
+}): VNode => {
+  const [{ path, params }, setState] = useState({
+    path: initialPath,
+    params: initialParams,
+  });
   if (typeof window === "undefined") {
-    throw Error("Can't use BrowserHashNavigationProvider if there is no window 
object")
+    throw Error(
+      "Can't use BrowserHashNavigationProvider if there is no window object",
+    );
   }
   function navigateTo(path: string) {
-    const { params } = getPathAndParamsFromWindow()
-    setState({ path, params })
-    window.location.href = path
+    const { params } = getPathAndParamsFromWindow();
+    setState({ path, params });
+    window.location.href = path;
   }
 
   useEffect(() => {
     function eventListener() {
-      setState(getPathAndParamsFromWindow())
+      setState(getPathAndParamsFromWindow());
     }
     window.addEventListener(PopStateEventType, eventListener);
     return () => {
-      window.removeEventListener(PopStateEventType, eventListener)
-    }
-  }, [])
+      window.removeEventListener(PopStateEventType, eventListener);
+    };
+  }, []);
   return h(Context.Provider, {
     value: { path, params, navigateTo },
     children,
diff --git a/packages/demobank-ui/src/context/wallet-integration.ts 
b/packages/demobank-ui/src/context/wallet-integration.ts
index 47bdc90ec..e14988ed1 100644
--- a/packages/demobank-ui/src/context/wallet-integration.ts
+++ b/packages/demobank-ui/src/context/wallet-integration.ts
@@ -14,47 +14,38 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import {
-  stringifyTalerUri,
-  TalerUri
-} from "@gnu-taler/taler-util";
-import {
-  ComponentChildren,
-  createContext,
-  h,
-  VNode
-} from "preact";
+import { stringifyTalerUri, TalerUri } from "@gnu-taler/taler-util";
+import { ComponentChildren, createContext, h, VNode } from "preact";
 import { useContext } from "preact/hooks";
 
 /**
  * https://docs.taler.net/design-documents/039-taler-browser-integration.html
- * 
- * @param uri 
+ *
+ * @param uri
  */
 function createHeadMetaTag(uri: TalerUri, onNotFound?: () => void) {
-
   const meta = document.createElement("meta");
   meta.setAttribute("name", "taler-uri");
   meta.setAttribute("content", stringifyTalerUri(uri));
 
   document.head.appendChild(meta);
 
-  let walletFound = false
+  let walletFound = false;
   window.addEventListener("beforeunload", () => {
-    walletFound = true
-  })
+    walletFound = true;
+  });
   setTimeout(() => {
     if (!walletFound && onNotFound) {
-      onNotFound()
+      onNotFound();
     }
-  }, 10)//very short timeout
+  }, 10); //very short timeout
 }
 interface Type {
   /**
    * Tell the active wallet that an action is found
-   * 
-   * @param uri 
-   * @returns 
+   *
+   * @param uri
+   * @returns
    */
   publishTalerAction: (uri: TalerUri, onNotFound?: () => void) => void;
 }
@@ -64,9 +55,13 @@ const Context = createContext<Type>(undefined);
 
 export const useTalerWalletIntegrationAPI = (): Type => useContext(Context);
 
-export const TalerWalletIntegrationBrowserProvider = ({ children }: { 
children: ComponentChildren }): VNode => {
+export const TalerWalletIntegrationBrowserProvider = ({
+  children,
+}: {
+  children: ComponentChildren;
+}): VNode => {
   const value: Type = {
-    publishTalerAction: createHeadMetaTag
+    publishTalerAction: createHeadMetaTag,
   };
   return h(Context.Provider, {
     value,
@@ -74,7 +69,6 @@ export const TalerWalletIntegrationBrowserProvider = ({ 
children }: { children:
   });
 };
 
-
 export const TalerWalletIntegrationTestingProvider = ({
   children,
   value,
@@ -82,7 +76,6 @@ export const TalerWalletIntegrationTestingProvider = ({
   children: ComponentChildren;
   value: Type;
 }): VNode => {
-
   return h(Context.Provider, {
     value,
     children,
diff --git a/packages/demobank-ui/src/index.html 
b/packages/demobank-ui/src/index.html
index 6e0638e3f..0789ecf89 100644
--- a/packages/demobank-ui/src/index.html
+++ b/packages/demobank-ui/src/index.html
@@ -17,25 +17,25 @@
 -->
 <!doctype html>
 <html lang="en" class="h-full bg-gray-100">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width,initial-scale=1" />
+    <meta name="taler-support" content="uri,api" />
+    <meta name="mobile-web-app-capable" content="yes" />
+    <meta name="apple-mobile-web-app-capable" content="yes" />
+    <link
+      rel="icon"
+      
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/
 [...]
+    />
+    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
+    <title>Bank</title>
+    <!-- Entry point for the bank SPA. -->
+    <script type="module" src="index.js"></script>
+    <link rel="stylesheet" href="index.css" />
+  </head>
 
-<head>
-  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width,initial-scale=1" />
-  <meta name="taler-support" content="uri,api" />
-  <meta name="mobile-web-app-capable" content="yes" />
-  <meta name="apple-mobile-web-app-capable" content="yes" />
-  <link rel="icon"
-    
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/Qn
 [...]
-  <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
-  <title>Bank</title>
-  <!-- Entry point for the bank SPA. -->
-  <script type="module" src="index.js"></script>
-  <link rel="stylesheet" href="index.css" />
-</head>
-
-<body class="h-full">
-  <div id="app"></div>
-</body>
-
-</html>
\ No newline at end of file
+  <body class="h-full">
+    <div id="app"></div>
+  </body>
+</html>
diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx 
b/packages/demobank-ui/src/pages/BankFrame.tsx
index a106f370d..d6ab882f1 100644
--- a/packages/demobank-ui/src/pages/BankFrame.tsx
+++ b/packages/demobank-ui/src/pages/BankFrame.tsx
@@ -174,15 +174,32 @@ export function BankFrame({
   );
 }
 
-function WelcomeAccount({ account: accountName }: { account: string }): VNode {
+function WelcomeAccount({ account }: { account: string }): VNode {
   const { i18n } = useTranslationContext();
+  const result = useAccountDetails(account);
+  if (!result) {
+    return <Loading />;
+  }
+  if (result instanceof TalerError) {
+    return <div />;
+  }
+  if (result.type === "fail") {
+    return (
+      <a
+        href={privatePages.myAccountDetails.url({})}
+        class="underline underline-offset-2"
+      >
+        <i18n.Translate>Welcome</i18n.Translate>
+      </a>
+    );
+  }
   return (
     <a
       href={privatePages.myAccountDetails.url({})}
       class="underline underline-offset-2"
     >
       <i18n.Translate>
-        Welcome, <span class="whitespace-nowrap">{accountName}</span>
+        Welcome, <span class="whitespace-nowrap">{result.body.name}</span>
       </i18n.Translate>
     </a>
   );
diff --git a/packages/demobank-ui/src/pages/DownloadStats.tsx 
b/packages/demobank-ui/src/pages/DownloadStats.tsx
index d149a0d9f..e53f1f4e2 100644
--- a/packages/demobank-ui/src/pages/DownloadStats.tsx
+++ b/packages/demobank-ui/src/pages/DownloadStats.tsx
@@ -398,7 +398,7 @@ export function DownloadStats({ routeCancel }: Props): 
VNode {
         >
           <Attention title={i18n.str`Download completed`}>
             <i18n.Translate>
-              click here to save the file in your computer
+              Click here to save the file in your computer.
             </i18n.Translate>
           </Attention>
         </a>
@@ -450,9 +450,9 @@ async function fetchAllStatus(
       // await delay()
       const previous = options.compareWithPrevious
         ? await api.getMonitor(token, {
-          timeframe: frame.timeframe,
-          which: frame.moment.previous,
-        })
+            timeframe: frame.timeframe,
+            which: frame.moment.previous,
+          })
         : undefined;
 
       if (previous && previous.type === "fail" && options.endOnFirstFail) {
diff --git a/packages/demobank-ui/src/pages/LoginForm.tsx 
b/packages/demobank-ui/src/pages/LoginForm.tsx
index 83aaff9fa..8acc79cfc 100644
--- a/packages/demobank-ui/src/pages/LoginForm.tsx
+++ b/packages/demobank-ui/src/pages/LoginForm.tsx
@@ -70,8 +70,8 @@ export function LoginForm({
       username: !username
         ? i18n.str`Missing username`
         : // : !USERNAME_REGEX.test(username)
-        //   ? i18n.str`Use letters and numbers only, and start with a 
lowercase letter`
-        undefined,
+          //   ? i18n.str`Use letters and numbers only, and start with a 
lowercase letter`
+          undefined,
       password: !password ? i18n.str`Missing password` : undefined,
     }) ?? busy;
 
@@ -153,7 +153,7 @@ export function LoginForm({
                 enterkeyhint="next"
                 placeholder="identification"
                 autocomplete="username"
-                title={i18n.str`username of the account`}
+                title={i18n.str`Username of the account`}
                 required
                 onInput={(e): void => {
                   setUsername(e.currentTarget.value);
@@ -185,7 +185,7 @@ export function LoginForm({
                 enterkeyhint="send"
                 value={password ?? ""}
                 placeholder="Password"
-                title={i18n.str`password of the account`}
+                title={i18n.str`Password of the account`}
                 required
                 onInput={(e): void => {
                   setPassword(e.currentTarget.value);
diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx 
b/packages/demobank-ui/src/pages/OperationState/views.tsx
index 4d193505e..dbd8e9b77 100644
--- a/packages/demobank-ui/src/pages/OperationState/views.tsx
+++ b/packages/demobank-ui/src/pages/OperationState/views.tsx
@@ -329,12 +329,12 @@ export function ReadyView({
   onAbort: doAbort,
 }: State.Ready): VNode<Record<string, never>> {
   const { i18n } = useTranslationContext();
-  const walletInegrationApi = useTalerWalletIntegrationAPI()
+  const walletInegrationApi = useTalerWalletIntegrationAPI();
   const [notification, notify, errorHandler] = useLocalNotification();
 
   const talerWithdrawUri = stringifyWithdrawUri(uri);
   useEffect(() => {
-    walletInegrationApi.publishTalerAction(uri)
+    walletInegrationApi.publishTalerAction(uri);
   }, []);
 
   async function onAbort() {
diff --git a/packages/demobank-ui/src/pages/PaymentOptions.tsx 
b/packages/demobank-ui/src/pages/PaymentOptions.tsx
index 51a6a17a9..eb21f637a 100644
--- a/packages/demobank-ui/src/pages/PaymentOptions.tsx
+++ b/packages/demobank-ui/src/pages/PaymentOptions.tsx
@@ -24,32 +24,42 @@ import { useTranslationContext } from 
"@gnu-taler/web-util/browser";
 import { useWithdrawalDetails } from "../hooks/access.js";
 import { useEffect } from "preact/hooks";
 
-function ShowOperationPendingTag({ woid, onOperationAlreadyCompleted }: { 
woid: string, onOperationAlreadyCompleted?: () => void }): VNode {
+function ShowOperationPendingTag({
+  woid,
+  onOperationAlreadyCompleted,
+}: {
+  woid: string;
+  onOperationAlreadyCompleted?: () => void;
+}): VNode {
   const { i18n } = useTranslationContext();
   const result = useWithdrawalDetails(woid);
-  const error = !result || result instanceof TalerError || result.type === 
"fail"
-  const completed = !error && (result.body.status === "aborted" || 
result.body.status === "confirmed")
+  const error =
+    !result || result instanceof TalerError || result.type === "fail";
+  const completed =
+    !error &&
+    (result.body.status === "aborted" || result.body.status === "confirmed");
   useEffect(() => {
     if (completed && onOperationAlreadyCompleted) {
-      onOperationAlreadyCompleted()
+      onOperationAlreadyCompleted();
     }
-  }, [completed])
+  }, [completed]);
 
   if (error || completed) {
     return <Fragment />;
   }
 
-  return <span class="flex items-center gap-x-1.5 w-fit rounded-md 
bg-green-100 px-2 py-1 text-xs font-medium text-green-700 whitespace-pre">
-    <svg
-      class="h-1.5 w-1.5 fill-green-500"
-      viewBox="0 0 6 6"
-      aria-hidden="true"
-    >
-      <circle cx="3" cy="3" r="3" />
-    </svg>
-    <i18n.Translate>operation ready</i18n.Translate>
-  </span>
-
+  return (
+    <span class="flex items-center gap-x-1.5 w-fit rounded-md bg-green-100 
px-2 py-1 text-xs font-medium text-green-700 whitespace-pre">
+      <svg
+        class="h-1.5 w-1.5 fill-green-500"
+        viewBox="0 0 6 6"
+        aria-hidden="true"
+      >
+        <circle cx="3" cy="3" r="3" />
+      </svg>
+      <i18n.Translate>Operation ready</i18n.Translate>
+    </span>
+  );
 }
 
 /**
@@ -128,9 +138,15 @@ export function PaymentOptions({
                   </i18n.Translate>
                 </div>
                 {!!bankState.currentWithdrawalOperationId && (
-                  <ShowOperationPendingTag 
woid={bankState.currentWithdrawalOperationId} onOperationAlreadyCompleted={() 
=> {
-                    updateBankState("currentWithdrawalOperationId", undefined)
-                  }} />
+                  <ShowOperationPendingTag
+                    woid={bankState.currentWithdrawalOperationId}
+                    onOperationAlreadyCompleted={() => {
+                      updateBankState(
+                        "currentWithdrawalOperationId",
+                        undefined,
+                      );
+                    }}
+                  />
                 )}
               </div>
             </label>
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx 
b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index 2259929e7..3643e1f6b 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -87,19 +87,19 @@ export function PaytoWireTransferForm({
 
   const errorsWire = undefinedIfEmpty({
     iban: !iban
-      ? i18n.str`required`
+      ? i18n.str`Required`
       : !IBAN_REGEX.test(iban)
         ? i18n.str`IBAN should have just uppercased letters and numbers`
         : validateIBAN(iban, i18n),
-    subject: !subject ? i18n.str`required` : undefined,
+    subject: !subject ? i18n.str`Required` : undefined,
     amount: !trimmedAmountStr
-      ? i18n.str`required`
+      ? i18n.str`Required`
       : !parsedAmount
-        ? i18n.str`not valid`
+        ? i18n.str`Not valid`
         : Amounts.isZero(parsedAmount)
-          ? i18n.str`should be greater than 0`
+          ? i18n.str`Should be greater than 0`
           : Amounts.cmp(limit, parsedAmount) === -1
-            ? i18n.str`balance is not enough`
+            ? i18n.str`Balance is not enough`
             : undefined,
   });
 
@@ -107,17 +107,17 @@ export function PaytoWireTransferForm({
 
   const errorsPayto = undefinedIfEmpty({
     rawPaytoInput: !rawPaytoInput
-      ? i18n.str`required`
+      ? i18n.str`Required`
       : !parsed
-        ? i18n.str`does not follow the pattern`
+        ? i18n.str`Does not follow the pattern`
         : !parsed.isKnown || parsed.targetType !== "iban"
-          ? i18n.str`only "IBAN" target are supported`
+          ? i18n.str`Only "IBAN" target are supported`
           : !parsed.params.amount
-            ? i18n.str`use the "amount" parameter to specify the amount to be 
transferred`
+            ? i18n.str`Use the "amount" parameter to specify the amount to be 
transferred`
             : Amounts.parse(parsed.params.amount) === undefined
-              ? i18n.str`the amount is not valid`
+              ? i18n.str`The amount is not valid`
               : !parsed.params.message
-                ? i18n.str`use the "message" parameter to specify a reference 
text for the transfer`
+                ? i18n.str`Use the "message" parameter to specify a reference 
text for the transfer`
                 : !IBAN_REGEX.test(parsed.iban)
                   ? i18n.str`IBAN should have just uppercased letters and 
numbers`
                   : validateIBAN(parsed.iban, i18n),
@@ -374,7 +374,7 @@ export function PaytoWireTransferForm({
                     name="subject"
                     id="subject"
                     autocomplete="off"
-                    placeholder={i18n.str`subject`}
+                    placeholder={i18n.str`Subject`}
                     value={subject ?? ""}
                     required
                     onInput={(e): void => {
@@ -388,7 +388,7 @@ export function PaytoWireTransferForm({
                 </div>
                 <p class="mt-2 text-sm text-gray-500">
                   <i18n.Translate>
-                    some text to identify the transfer
+                    Some text to identify the transfer
                   </i18n.Translate>
                 </p>
               </div>
@@ -412,7 +412,7 @@ export function PaytoWireTransferForm({
                   isDirty={trimmedAmountStr !== undefined}
                 />
                 <p class="mt-2 text-sm text-gray-500">
-                  <i18n.Translate>amount to transfer</i18n.Translate>
+                  <i18n.Translate>Amount to transfer</i18n.Translate>
                 </p>
               </div>
             </div>
@@ -422,7 +422,7 @@ export function PaytoWireTransferForm({
                 <label
                   for="address"
                   class="block text-sm font-medium leading-6 text-gray-900"
-                >{i18n.str`payto URI:`}</label>
+                >{i18n.str`Payto URI:`}</label>
                 <div class="mt-2">
                   <textarea
                     ref={focus ? doAutoFocus : undefined}
@@ -433,7 +433,7 @@ export function PaytoWireTransferForm({
                     class="block overflow-hidden w-44 sm:w-96 rounded-md 
border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 
placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 
sm:text-sm sm:leading-6"
                     value={rawPaytoInput ?? ""}
                     required
-                    title={i18n.str`uniform resource identifier of the target 
account`}
+                    title={i18n.str`Uniform resource identifier of the target 
account`}
                     
placeholder={i18n.str`payto://iban/[receiver-iban]?message=[subject]&amount=[${limit.currency}:X.Y]`}
                     onInput={(e): void => {
                       rawPaytoInputSetter(e.currentTarget.value);
diff --git a/packages/demobank-ui/src/pages/ProfileNavigation.tsx 
b/packages/demobank-ui/src/pages/ProfileNavigation.tsx
index 02f30d8e8..607487c9d 100644
--- a/packages/demobank-ui/src/pages/ProfileNavigation.tsx
+++ b/packages/demobank-ui/src/pages/ProfileNavigation.tsx
@@ -33,7 +33,7 @@ export function ProfileNavigation({
     credentials.status !== "loggedIn"
       ? false
       : !credentials.isUserAdministrator;
-  const { navigateTo } = useNavigationContext()
+  const { navigateTo } = useNavigationContext();
   return (
     <div>
       <div class="sm:hidden">
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx 
b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index 037849804..bf0369855 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -19,7 +19,7 @@ import {
   HttpStatusCode,
   stringifyWithdrawUri,
   TranslatedString,
-  WithdrawUriResult
+  WithdrawUriResult,
 } from "@gnu-taler/taler-util";
 import {
   LocalNotificationBanner,
@@ -41,13 +41,13 @@ export function QrCodeSection({
   onAborted: () => void;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const walletInegrationApi = useTalerWalletIntegrationAPI()
+  const walletInegrationApi = useTalerWalletIntegrationAPI();
   const talerWithdrawUri = stringifyWithdrawUri(withdrawUri);
   const { state: credentials } = useBackendState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
 
   useEffect(() => {
-    walletInegrationApi.publishTalerAction(withdrawUri)
+    walletInegrationApi.publishTalerAction(withdrawUri);
   }, []);
 
   const [notification, notify, handleError] = useLocalNotification();
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx 
b/packages/demobank-ui/src/pages/RegistrationPage.tsx
index 931a9b700..b7b02b76d 100644
--- a/packages/demobank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx
@@ -218,7 +218,9 @@ function RegistrationForm({
       ? "123"
       : getRandomPassword();
     const username = `_${user.first}-${user.second}_`;
-    const name = `${user.first}, ${user.second}`;
+    const name = `${capitalizeFirstLetter(user.first)} ${capitalizeFirstLetter(
+      user.second,
+    )}`;
     await doRegistrationAndLogin(name, username, password, () => {
       onRegistrationSuccesful(username, password);
     });
@@ -248,7 +250,7 @@ function RegistrationForm({
                 for="username"
                 class="block text-sm font-medium leading-6 text-gray-900"
               >
-                <i18n.Translate>Username</i18n.Translate>
+                <i18n.Translate>Login username</i18n.Translate>
                 <b style={{ color: "red" }}> *</b>
               </label>
               <div class="mt-2">
@@ -260,7 +262,7 @@ function RegistrationForm({
                   class="block w-full rounded-md border-0 py-1.5 text-gray-900 
shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 
focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                   value={username ?? ""}
                   enterkeyhint="next"
-                  placeholder="identification"
+                  placeholder="account identification to login"
                   autocomplete="username"
                   required
                   onInput={(e): void => {
@@ -344,7 +346,7 @@ function RegistrationForm({
                   for="name"
                   class="block text-sm font-medium leading-6 text-gray-900"
                 >
-                  <i18n.Translate>Name</i18n.Translate>
+                  <i18n.Translate>Full name</i18n.Translate>
                   <b style={{ color: "red" }}> *</b>
                 </label>
               </div>
@@ -357,7 +359,7 @@ function RegistrationForm({
                   class="block w-full rounded-md border-0 py-1.5 text-gray-900 
shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 
focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                   value={name ?? ""}
                   enterkeyhint="next"
-                  placeholder="your name"
+                  placeholder="John Doe"
                   autocomplete="name"
                   required
                   onInput={(e): void => {
@@ -463,3 +465,7 @@ function RegistrationForm({
     </Fragment>
   );
 }
+
+function capitalizeFirstLetter(str: string) {
+  return str.charAt(0).toUpperCase() + str.slice(1);
+}
diff --git a/packages/demobank-ui/src/pages/SolveChallengePage.tsx 
b/packages/demobank-ui/src/pages/SolveChallengePage.tsx
index 8c39b8d94..de0ba483f 100644
--- a/packages/demobank-ui/src/pages/SolveChallengePage.tsx
+++ b/packages/demobank-ui/src/pages/SolveChallengePage.tsx
@@ -78,7 +78,7 @@ export function SolveChallengePage({
 
   const ch = bankState.currentChallenge;
   const errors = undefinedIfEmpty({
-    code: !code ? i18n.str`required` : undefined,
+    code: !code ? i18n.str`Required` : undefined,
   });
 
   async function startChallenge() {
@@ -255,6 +255,10 @@ export function SolveChallengePage({
           <ChallengeDetails
             challenge={bankState.currentChallenge}
             onStart={startChallenge}
+            onCancel={() => {
+              updateBankState("currentChallenge", undefined);
+              onChallengeCompleted();
+            }}
           />
           {ch.info && (
             <div class="mt-3 text-sm leading-6">
@@ -325,9 +329,11 @@ export function SolveChallengePage({
 function ChallengeDetails({
   challenge,
   onStart,
+  onCancel,
 }: {
   challenge: ChallengeInProgess;
   onStart: () => void;
+  onCancel: () => void;
 }): VNode {
   const { i18n, dateLocale } = useTranslationContext();
   const { config } = useBankCoreApiContext();
@@ -335,7 +341,15 @@ function ChallengeDetails({
   return (
     <div class="px-4 mt-4 ">
       <div class="w-full">
-        <div class="flex justify-center">
+        <div class="flex justify-between">
+          <button
+            type="button"
+            // class="disabled:opacity-50 disabled:cursor-default 
cursor-pointer rounded-md  px-3 py-2 text-sm font-semibold text-black shadow-sm 
hover:bg-red-500 focus-visible:outline focus-visible:outline-2 
focus-visible:outline-offset-2 focus-visible:outline-red-600"
+            class="text-sm font-semibold leading-6 text-gray-900"
+            onClick={onCancel}
+          >
+            <i18n.Translate>Cancel</i18n.Translate>
+          </button>
           {challenge.info ? (
             <button
               type="submit"
@@ -376,7 +390,7 @@ function ChallengeDetails({
                   return (
                     <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                       <dt class="text-sm font-medium leading-6 text-gray-900">
-                        Account
+                        <i18n.Translate>Account</i18n.Translate>
                       </dt>
                       <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                         {challenge.request}
@@ -390,7 +404,7 @@ function ChallengeDetails({
                       {challenge.request.amount && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Amount
+                            <i18n.Translate>Amount</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             <RenderAmount
@@ -405,7 +419,7 @@ function ChallengeDetails({
                       {payto.isKnown && payto.targetType === "iban" && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            To account
+                            <i18n.Translate>To account</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             {payto.iban}
@@ -426,7 +440,7 @@ function ChallengeDetails({
                       {challenge.request.cashout_payto_uri !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Cashout account
+                            <i18n.Translate>Cashout account</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             {challenge.request.cashout_payto_uri}
@@ -436,7 +450,7 @@ function ChallengeDetails({
                       {challenge.request.contact_data?.email !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Email
+                            <i18n.Translate>Email</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             {challenge.request.contact_data?.email}
@@ -446,7 +460,7 @@ function ChallengeDetails({
                       {challenge.request.contact_data?.phone !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Phone
+                            <i18n.Translate>Phone</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             {challenge.request.contact_data?.phone}
@@ -456,7 +470,7 @@ function ChallengeDetails({
                       {challenge.request.debit_threshold !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Debit threshold
+                            <i18n.Translate>Debit threshold</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             <RenderAmount
@@ -471,17 +485,21 @@ function ChallengeDetails({
                       {challenge.request.is_public !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Is this account public?
+                            <i18n.Translate>
+                              Is this account public?
+                            </i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
-                            {challenge.request.is_public ? "enable" : 
"disable"}
+                            {challenge.request.is_public
+                              ? i18n.str`Enable`
+                              : i18n.str`Disable`}
                           </dd>
                         </div>
                       )}
                       {challenge.request.name !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Name
+                            <i18n.Translate>Name</i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                             {challenge.request.name}
@@ -491,10 +509,12 @@ function ChallengeDetails({
                       {challenge.request.tan_channel !== undefined && (
                         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                           <dt class="text-sm font-medium leading-6 
text-gray-900">
-                            Authentication channel
+                            <i18n.Translate>
+                              Authentication channel
+                            </i18n.Translate>
                           </dt>
                           <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
-                            {challenge.request.tan_channel}
+                            {challenge.request.tan_channel ?? i18n.str`Remove`}
                           </dd>
                         </div>
                       )}
@@ -506,7 +526,7 @@ function ChallengeDetails({
                     <Fragment>
                       <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 
sm:px-0">
                         <dt class="text-sm font-medium leading-6 
text-gray-900">
-                          New password
+                          <i18n.Translate>New password</i18n.Translate>
                         </dt>
                         <dd class="mt-1 text-sm leading-6 text-gray-700 
sm:col-span-2 sm:mt-0">
                           {challenge.request.new_password}
@@ -570,6 +590,7 @@ function ChallengeDetails({
 
 function ShowWithdrawalDetails({ id }: { id: string }): VNode {
   const details = useWithdrawalDetails(id);
+  const { i18n } = useTranslationContext();
   const { config } = useBankCoreApiContext();
   if (!details) {
     return <Loading />;
@@ -601,7 +622,7 @@ function ShowWithdrawalDetails({ id }: { id: string }): 
VNode {
       {details.body.selected_reserve_pub !== undefined && (
         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
           <dt class="text-sm font-medium leading-6 text-gray-900">
-            Withdraw id
+            <i18n.Translate>Withdraw id</i18n.Translate>
           </dt>
           <dd
             class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"
@@ -614,7 +635,7 @@ function ShowWithdrawalDetails({ id }: { id: string }): 
VNode {
       {details.body.selected_exchange_account !== undefined && (
         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
           <dt class="text-sm font-medium leading-6 text-gray-900">
-            To account
+            <i18n.Translate>To account</i18n.Translate>
           </dt>
           <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 
sm:mt-0">
             {details.body.selected_exchange_account}
@@ -658,7 +679,9 @@ function ShowCashoutDetails({
     <Fragment>
       {request.subject !== undefined && (
         <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
-          <dt class="text-sm font-medium leading-6 text-gray-900">Subject</dt>
+          <dt class="text-sm font-medium leading-6 text-gray-900">
+            <i18n.Translate>Subject</i18n.Translate>
+          </dt>
           <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 
sm:mt-0">
             {request.subject}
           </dd>
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx 
b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index 9f7f46c4f..8ce4c6a09 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -85,7 +85,7 @@ function OldWithdrawalForm({
     // const uri = parseWithdrawUri(suri)!
     const url = privatePages.operationDetails.url({
       wopid: bankState.currentWithdrawalOperationId,
-    })
+    });
     return (
       <Attention type="warning" title={i18n.str`There is an operation 
already`}>
         <span ref={focus ? doAutoFocus : undefined} />
@@ -95,12 +95,12 @@ function OldWithdrawalForm({
         <a
           class="font-semibold text-yellow-700 hover:text-yellow-600"
           href={url}
-        // onClick={(e) => {
-        //   e.preventDefault()
-        //   walletInegrationApi.publishTalerAction(uri, () => {
-        //     navigateTo(url)
-        //   })
-        // }}
+          // onClick={(e) => {
+          //   e.preventDefault()
+          //   walletInegrationApi.publishTalerAction(uri, () => {
+          //     navigateTo(url)
+          //   })
+          // }}
         >
           <i18n.Translate>this page</i18n.Translate>
         </a>
@@ -117,11 +117,11 @@ function OldWithdrawalForm({
   const errors = undefinedIfEmpty({
     amount:
       trimmedAmountStr == null
-        ? i18n.str`required`
+        ? i18n.str`Required`
         : !parsedAmount
-          ? i18n.str`invalid`
+          ? i18n.str`Invalid`
           : Amounts.cmp(limit, parsedAmount) === -1
-            ? i18n.str`balance is not enough`
+            ? i18n.str`Balance is not enough`
             : undefined,
   });
 
@@ -345,7 +345,7 @@ export function WalletWithdrawForm({
             onAuthorizationRequired={onAuthorizationRequired}
             routeClose={routeCancel}
             onAbort={onOperationAborted}
-          // route={routeCancel}
+            // route={routeCancel}
           />
         )}
       </div>
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx 
b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index 03f6556af..a23909338 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -78,8 +78,17 @@ export function WithdrawalQRCode({
       <div class="relative ml-auto mr-auto transform overflow-hidden 
rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 
sm:w-full sm:max-w-sm sm:p-6">
         <div>
           <div class="mx-auto flex h-12 w-12 items-center justify-center 
rounded-full bg-yellow-100">
-            <svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" 
fill="currentColor" aria-hidden="true">
-              <path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 
3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 
0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 
01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" 
clip-rule="evenodd" />
+            <svg
+              class="h-5 w-5 text-yellow-400"
+              viewBox="0 0 20 20"
+              fill="currentColor"
+              aria-hidden="true"
+            >
+              <path
+                fill-rule="evenodd"
+                d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 
1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 
2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 
1 0 100-2 1 1 0 000 2z"
+                clip-rule="evenodd"
+              />
             </svg>
           </div>
           <div class="mt-3 text-center sm:mt-5">
diff --git a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx 
b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
index 9f8fb72bc..6d5a1c18d 100644
--- a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
@@ -61,7 +61,7 @@ export function ShowAccountDetails({
       ? credentials.username === account
       : false;
 
-  const [update, setUpdate] = useState(false);
+  // const [update, setUpdate] = useState(false);
   const [submitAccount, setSubmitAccount] = useState<
     TalerCorebankApi.AccountReconfiguration | undefined
   >();
@@ -86,7 +86,7 @@ export function ShowAccountDetails({
   }
 
   async function doUpdate() {
-    if (!update || !submitAccount || !creds) return;
+    if (!submitAccount || !creds) return;
     await handleError(async () => {
       const resp = await api.updateAccount(
         {
@@ -190,7 +190,7 @@ export function ShowAccountDetails({
                   <i18n.Translate>Change details</i18n.Translate>
                 </span>
               </span>
-              <button
+              {/* <button
                 type="button"
                 data-enabled={!update}
                 class="bg-indigo-600 data-[enabled=true]:bg-gray-200 relative 
inline-flex h-5 w-10 flex-shrink-0 cursor-pointer rounded-full ring-2 
border-gray-600 transition-colors duration-200 ease-in-out focus:outline-none 
focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
@@ -207,16 +207,16 @@ export function ShowAccountDetails({
                   data-enabled={!update}
                   class="translate-x-5 data-[enabled=true]:translate-x-0 
pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow 
ring-0 transition duration-200 ease-in-out"
                 ></span>
-              </button>
+              </button> */}
             </div>
           </h2>
         </div>
 
         <AccountForm
-          focus={update}
+          focus={true}
           username={account}
           template={result.body}
-          purpose={update ? "update" : "show"}
+          purpose="update"
           onChange={(a) => setSubmitAccount(a)}
         >
           <div class="flex items-center justify-between gap-x-6 border-t 
border-gray-900/10 px-4 py-4 sm:px-8">
@@ -229,7 +229,7 @@ export function ShowAccountDetails({
             <button
               type="submit"
               class="disabled:opacity-50 disabled:cursor-default 
cursor-pointer rounded-md bg-indigo-600 px-3 py-2 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"
-              disabled={!update || !submitAccount}
+              disabled={!submitAccount}
               onClick={doUpdate}
             >
               <i18n.Translate>Update</i18n.Translate>
diff --git a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx 
b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
index 3b35c1fe1..4dcce599d 100644
--- a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
+++ b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
@@ -69,13 +69,13 @@ export function UpdateAccountPassword({
     current: !accountIsTheCurrentUser
       ? undefined
       : !current
-        ? i18n.str`required`
+        ? i18n.str`Required`
         : undefined,
-    password: !password ? i18n.str`required` : undefined,
+    password: !password ? i18n.str`Required` : undefined,
     repeat: !repeat
-      ? i18n.str`required`
+      ? i18n.str`Required`
       : password !== repeat
-        ? i18n.str`password doesn't match`
+        ? i18n.str`Repeated password doesn't match`
         : undefined,
   });
   const [notification, notify, handleError] = useLocalNotification();
@@ -214,7 +214,7 @@ export function UpdateAccountPassword({
                   />
                 </div>
                 <p class="mt-2 text-sm text-gray-500">
-                  <i18n.Translate>repeat the same password</i18n.Translate>
+                  <i18n.Translate>Repeat the same password</i18n.Translate>
                 </p>
               </div>
 
@@ -246,7 +246,7 @@ export function UpdateAccountPassword({
                   </div>
                   <p class="mt-2 text-sm text-gray-500">
                     <i18n.Translate>
-                      your current password, for security
+                      Your current password, for security
                     </i18n.Translate>
                   </p>
                 </div>
diff --git a/packages/demobank-ui/src/pages/admin/AccountForm.tsx 
b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
index 8465a3d8f..fcad47b4a 100644
--- a/packages/demobank-ui/src/pages/admin/AccountForm.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
@@ -128,6 +128,8 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
   const editableName =
     purpose === "create" ||
     (purpose === "update" && (config.allow_edit_name || userIsAdmin));
+
+  const isCashoutEnabled = config.allow_conversion;
   const editableCashout =
     showingCurrentUserInfo &&
     (purpose === "create" ||
@@ -162,9 +164,9 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
         : !editableCashout
           ? undefined
           : !cashoutParsed
-            ? i18n.str`it doesn't have the pattern of an IBAN number`
+            ? i18n.str`Doesn't have the pattern of an IBAN number`
             : !cashoutParsed.isKnown || cashoutParsed.targetType !== "iban"
-              ? i18n.str`only "IBAN" target are supported`
+              ? i18n.str`Only "IBAN" target are supported`
               : !IBAN_REGEX.test(cashoutParsed.iban)
                 ? i18n.str`IBAN should have just uppercased letters and 
numbers`
                 : validateIBAN(cashoutParsed.iban, i18n),
@@ -173,40 +175,40 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
         : !editableAccount
           ? undefined
           : !internalParsed
-            ? i18n.str`it doesn't have the pattern of an IBAN number`
+            ? i18n.str`Doesn't have the pattern of an IBAN number`
             : !internalParsed.isKnown || internalParsed.targetType !== "iban"
-              ? i18n.str`only "IBAN" target are supported`
+              ? i18n.str`Only "IBAN" target are supported`
               : !IBAN_REGEX.test(internalParsed.iban)
                 ? i18n.str`IBAN should have just uppercased letters and 
numbers`
                 : validateIBAN(internalParsed.iban, i18n),
       email: !newForm.email
         ? undefined
         : !EMAIL_REGEX.test(newForm.email)
-          ? i18n.str`it doesn't have the pattern of an email`
+          ? i18n.str`Doesn't have the pattern of an email`
           : undefined,
       phone: !newForm.phone
         ? undefined
         : !newForm.phone.startsWith("+") // FIXME: better phone number check
-          ? i18n.str`should start with +`
+          ? i18n.str`Should start with +`
           : !REGEX_JUST_NUMBERS_REGEX.test(newForm.phone)
-            ? i18n.str`phone number can't have other than numbers`
+            ? i18n.str`Phone number can't have other than numbers`
             : undefined,
       debit_threshold: !editableThreshold
         ? undefined
         : !trimmedAmountStr
           ? undefined
           : !parsedAmount
-            ? i18n.str`not valid`
+            ? i18n.str`Not valid`
             : undefined,
       name: !editableName
         ? undefined // disabled
         : !newForm.name
-          ? i18n.str`required`
+          ? i18n.str`Required`
           : undefined,
       username: !editableUsername
         ? undefined
         : !newForm.username
-          ? i18n.str`required`
+          ? i18n.str`Required`
           : undefined,
     });
     setErrors(errors);
@@ -246,8 +248,8 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
             debit_threshold: threshold ?? config.default_debit_threshold,
             cashout_payto_uri: cashoutURI,
             payto_uri: internalURI,
-            is_public: !!newForm.isPublic,
-            is_taler_exchange: !!newForm.isExchange,
+            is_public: newForm.isPublic,
+            is_taler_exchange: newForm.isExchange,
             tan_channel:
               newForm.tan_channel === "remove"
                 ? undefined
@@ -263,11 +265,11 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
           const result: TalerCorebankApi.AccountReconfiguration = {
             cashout_payto_uri: cashoutURI,
             contact_data: undefinedIfEmpty({
-              email: newForm.email ?? template?.contact_data?.email,
-              phone: newForm.phone ?? template?.contact_data?.phone,
+              email: newForm.email,
+              phone: newForm.phone,
             }),
             debit_threshold: threshold,
-            is_public: !!newForm.isPublic,
+            is_public: newForm.isPublic,
             name: newForm.name,
             tan_channel:
               newForm.tan_channel === "remove" ? null : newForm.tan_channel,
@@ -300,7 +302,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
               class="block text-sm font-medium leading-6 text-gray-900"
               for="username"
             >
-              {i18n.str`Username`}
+              {i18n.str`Login username`}
               {editableUsername && <b style={{ color: "red" }}> *</b>}
             </label>
             <div class="mt-2">
@@ -326,9 +328,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
               />
             </div>
             <p class="mt-2 text-sm text-gray-500">
-              <i18n.Translate>
-                account identification in the bank
-              </i18n.Translate>
+              <i18n.Translate>Account identification</i18n.Translate>
             </p>
           </div>
 
@@ -337,7 +337,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
               class="block text-sm font-medium leading-6 text-gray-900"
               for="name"
             >
-              {i18n.str`Name`}
+              {i18n.str`Full name`}
               {editableName && <b style={{ color: "red" }}> *</b>}
             </label>
             <div class="mt-2">
@@ -362,9 +362,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
               />
             </div>
             <p class="mt-2 text-sm text-gray-500">
-              <i18n.Translate>
-                name of the person owner the account
-              </i18n.Translate>
+              <i18n.Translate>Name of the account holder</i18n.Translate>
             </p>
           </div>
 
@@ -374,8 +372,8 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
             label={i18n.str`Internal IBAN`}
             help={
               purpose === "create"
-                ? i18n.str`if empty a random account number will be assigned`
-                : i18n.str`account identification for bank transfer`
+                ? i18n.str`If empty a random account number will be assigned`
+                : i18n.str`Account number for bank transfers`
             }
             value={(form.payto_uri ?? defaultValue.payto_uri) as PaytoString}
             disabled={!editableAccount}
@@ -444,12 +442,12 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
             </div>
           </div>
 
-          {showingCurrentUserInfo && (
+          {showingCurrentUserInfo && isCashoutEnabled && (
             <PaytoField
               type="iban"
               name="cashout-account"
               label={i18n.str`Cashout IBAN`}
-              help={i18n.str`account number where the money is going to be 
sent when doing cashouts`}
+              help={i18n.str`External account number where the money is going 
to be sent when doing cashouts`}
               value={
                 (form.cashout_payto_uri ??
                   defaultValue.cashout_payto_uri) as PaytoString
@@ -477,9 +475,9 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
                 !editableThreshold
                   ? undefined
                   : (e) => {
-                    form.debit_threshold = e as AmountString;
-                    updateForm(structuredClone(form));
-                  }
+                      form.debit_threshold = e as AmountString;
+                      updateForm(structuredClone(form));
+                    }
               }
             />
             <ShowInputErrorLabel
@@ -492,7 +490,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
             />
             <p class="mt-2 text-sm text-gray-500">
               <i18n.Translate>
-                how much is user able to transfer after zero balance
+                How much is user able to transfer after zero balance
               </i18n.Translate>
             </p>
           </div>
@@ -539,19 +537,8 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
             </div>
           )}
           {/* channel, not shown if old cashout api */}
-          {OLD_CASHOUT_API ? undefined : config.supported_tan_channels
-            .length === 0 ? (
-            <div class="sm:col-span-5">
-              <Attention
-                type="warning"
-                title={i18n.str`No cashout channel available`}
-              >
-                <i18n.Translate>
-                  This server doesn't support second factor authentication.
-                </i18n.Translate>
-              </Attention>
-            </div>
-          ) : (
+          {OLD_CASHOUT_API ||
+          config.supported_tan_channels.length === 0 ? undefined : (
             <div class="sm:col-span-5">
               <label
                 class="block text-sm font-medium leading-6 text-gray-900"
@@ -562,7 +549,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
               <div class="mt-2 max-w-xl text-sm text-gray-500">
                 <div class="px-4 mt-4 grid grid-cols-1 gap-y-6">
                   {config.supported_tan_channels.indexOf(TanChannel.EMAIL) ===
-                    -1 ? undefined : (
+                  -1 ? undefined : (
                     <label
                       onClick={(e) => {
                         if (!hasEmail) return;
@@ -597,7 +584,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
                           </span>
                           {purpose !== "show" &&
                             !hasEmail &&
-                            i18n.str`add a email in your profile to enable 
this option`}
+                            i18n.str`Add a email in your profile to enable 
this option`}
                         </span>
                       </span>
                       <svg
@@ -620,7 +607,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
                   )}
 
                   {config.supported_tan_channels.indexOf(TanChannel.SMS) ===
-                    -1 ? undefined : (
+                  -1 ? undefined : (
                     <label
                       onClick={(e) => {
                         if (!hasPhone) return;
@@ -655,7 +642,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
                           </span>
                           {purpose !== "show" &&
                             !hasPhone &&
-                            i18n.str`add a phone number in your profile to 
enable this option`}
+                            i18n.str`Add a phone number in your profile to 
enable this option`}
                         </span>
                       </span>
                       <svg
@@ -702,7 +689,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
                 aria-labelledby="availability-label"
                 aria-describedby="availability-description"
                 onClick={() => {
-                  form.isPublic = !form.isPublic;
+                  form.isPublic = !(form.isPublic ?? defaultValue.isPublic);
                   updateForm(structuredClone(form));
                 }}
               >
@@ -717,7 +704,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
             </div>
             <p class="mt-2 text-sm text-gray-500">
               <i18n.Translate>
-                public accounts have their balance publicly accessible
+                Public accounts have their balance publicly accessible
               </i18n.Translate>
             </p>
           </div>
diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx 
b/packages/demobank-ui/src/pages/admin/AccountList.tsx
index 1cee4c58a..41d54c43d 100644
--- a/packages/demobank-ui/src/pages/admin/AccountList.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx
@@ -149,7 +149,7 @@ export function AccountList({
                             class="whitespace-nowrap px-3 py-4 text-sm 
text-gray-500 data-[negative=false]:text-green-600 
data-[negative=true]:text-red-600 "
                           >
                             {!balance ? (
-                              i18n.str`unknown`
+                              i18n.str`Unknown`
                             ) : (
                               <span class="amount">
                                 <RenderAmount
@@ -167,7 +167,7 @@ export function AccountList({
                               })}
                               class="text-indigo-600 hover:text-indigo-900"
                             >
-                              <i18n.Translate>change password</i18n.Translate>
+                              <i18n.Translate>Change password</i18n.Translate>
                             </a>
                             <br />
                             <a
@@ -176,7 +176,7 @@ export function AccountList({
                               })}
                               class="text-indigo-600 hover:text-indigo-900"
                             >
-                              <i18n.Translate>cashouts</i18n.Translate>
+                              <i18n.Translate>Cashouts</i18n.Translate>
                             </a>
                             <br />
                             {noBalance ? (
@@ -186,7 +186,7 @@ export function AccountList({
                                 })}
                                 class="text-indigo-600 hover:text-indigo-900"
                               >
-                                <i18n.Translate>remove</i18n.Translate>
+                                <i18n.Translate>Remove</i18n.Translate>
                               </a>
                             ) : undefined}
                           </td>
diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx 
b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
index 84cc982af..f0f8f71be 100644
--- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx
+++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
@@ -335,7 +335,7 @@ function Metrics(): VNode {
       </div>
       <dl class="mt-5 grid grid-cols-1 md:grid-cols-2  divide-y 
divide-gray-200 overflow-hidden rounded-lg bg-white shadow-lg md:divide-x 
md:divide-y-0">
         {resp.current.body.type !== "with-conversions" ||
-          resp.previous.body.type !== "with-conversions" ? undefined : (
+        resp.previous.body.type !== "with-conversions" ? undefined : (
           <Fragment>
             <div class="px-4 py-5 sm:p-6">
               <dt class="text-base font-normal text-gray-900">
@@ -385,7 +385,7 @@ function Metrics(): VNode {
           href={privatePages.statsDownload.url({})}
           class="disabled:opacity-50 disabled:cursor-default cursor-pointer 
rounded-md bg-indigo-600 px-3 py-2 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"
         >
-          <i18n.Translate>download stats as CSV</i18n.Translate>
+          <i18n.Translate>Download stats as CSV</i18n.Translate>
         </a>
       </div>
     </Fragment>
@@ -411,9 +411,9 @@ function MetricValue({
 
   const rate =
     !currAmount ||
-      Number.isNaN(currAmount) ||
-      !prevAmount ||
-      Number.isNaN(prevAmount)
+    Number.isNaN(currAmount) ||
+    !prevAmount ||
+    Number.isNaN(prevAmount)
       ? 0
       : cmp === -1
         ? 1 - Math.round(currAmount) / Math.round(prevAmount)
diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx 
b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
index 36e1a4eac..e62b6dc03 100644
--- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
@@ -165,9 +165,9 @@ export function RemoveAccount({
 
   const errors = undefinedIfEmpty({
     accountName: !accountName
-      ? i18n.str`required`
+      ? i18n.str`Required`
       : account !== accountName
-        ? i18n.str`name doesn't match`
+        ? i18n.str`Name doesn't match`
         : undefined,
   });
 
@@ -229,7 +229,7 @@ export function RemoveAccount({
                 </div>
                 <p class="mt-2 text-sm text-gray-500">
                   <i18n.Translate>
-                    enter the account name that is going to be deleted
+                    Enter the account name that is going to be deleted
                   </i18n.Translate>
                 </p>
               </div>
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx 
b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 46da5c847..8ec34276f 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -188,7 +188,8 @@ export function CreateCashout({
    * depending on the isDebit flag
    */
   const inputAmount = Amounts.parseOrThrow(
-    `${form.isDebit ? regional_currency : fiat_currency}:${!form.amount ? "0" 
: form.amount
+    `${form.isDebit ? regional_currency : fiat_currency}:${
+      !form.amount ? "0" : form.amount
     }`,
   );
 
@@ -212,19 +213,19 @@ export function CreateCashout({
     setForm(newForm);
   }
   const errors = undefinedIfEmpty<ErrorFrom<typeof form>>({
-    subject: !form.subject ? i18n.str`required` : undefined,
+    subject: !form.subject ? i18n.str`Required` : undefined,
     amount: !form.amount
-      ? i18n.str`required`
+      ? i18n.str`Required`
       : !inputAmount
-        ? i18n.str`invalid`
+        ? i18n.str`Invalid`
         : Amounts.cmp(limit, calc.debit) === -1
-          ? i18n.str`balance is not enough`
+          ? i18n.str`Balance is not enough`
           : Amounts.cmp(calc.credit, sellFee) === -1
-            ? i18n.str`need to be higher due to fees`
+            ? i18n.str`Need to be higher due to fees`
             : Amounts.isZero(calc.credit)
-              ? i18n.str`the total transfer at destination will be zero`
+              ? i18n.str`The total transfer at destination will be zero`
               : undefined,
-    channel: OLD_CASHOUT_API && !form.channel ? i18n.str`required` : undefined,
+    channel: OLD_CASHOUT_API && !form.channel ? i18n.str`Required` : undefined,
   });
   const trimmedAmountStr = form.amount?.trim();
 
@@ -470,9 +471,9 @@ export function CreateCashout({
                       cashoutDisabled
                         ? undefined
                         : (value) => {
-                          form.amount = value;
-                          updateForm(structuredClone(form));
-                        }
+                            form.amount = value;
+                            updateForm(structuredClone(form));
+                          }
                     }
                   />
                   <ShowInputErrorLabel
@@ -513,7 +514,7 @@ export function CreateCashout({
                       </dd>
                     </div>
                     {Amounts.isZero(sellFee) ||
-                      Amounts.isZero(calc.beforeFee) ? undefined : (
+                    Amounts.isZero(calc.beforeFee) ? undefined : (
                       <div class="flex items-center justify-between border-t-2 
afu pt-4">
                         <dt class="flex items-center text-sm text-gray-600">
                           <span>
@@ -546,7 +547,7 @@ export function CreateCashout({
 
               {/* channel, not shown if new cashout api */}
               {!OLD_CASHOUT_API ? undefined : config.supported_tan_channels
-                .length === 0 ? (
+                  .length === 0 ? (
                 <div class="sm:col-span-5">
                   <Attention
                     type="warning"
@@ -598,7 +599,7 @@ export function CreateCashout({
                                 <i18n.Translate>Email</i18n.Translate>
                               </span>
                               {!resultAccount.body.contact_data?.email &&
-                                i18n.str`add a email in your profile to enable 
this option`}
+                                i18n.str`Add a email in your profile to enable 
this option`}
                             </span>
                           </span>
                           <svg
@@ -618,7 +619,7 @@ export function CreateCashout({
                       )}
 
                       {config.supported_tan_channels.indexOf(TanChannel.SMS) 
===
-                        -1 ? undefined : (
+                      -1 ? undefined : (
                         <label
                           onClick={() => {
                             if (!resultAccount.body.contact_data?.phone) 
return;
@@ -646,7 +647,7 @@ export function CreateCashout({
                                 <i18n.Translate>SMS</i18n.Translate>
                               </span>
                               {!resultAccount.body.contact_data?.phone &&
-                                i18n.str`add a phone number in your profile to 
enable this option`}
+                                i18n.str`Add a phone number in your profile to 
enable this option`}
                             </span>
                           </span>
                           <svg
diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx 
b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
index 589e29793..7b251d3ca 100644
--- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
+++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
@@ -46,7 +46,7 @@ export function ShowCashoutDetails({ id, routeClose }: 
Props): VNode {
     return (
       <Attention
         type="danger"
-        title={i18n.str`cashout id should be a number`}
+        title={i18n.str`Cashout id should be a number`}
       />
     );
   }
diff --git a/packages/demobank-ui/src/route.ts 
b/packages/demobank-ui/src/route.ts
index 912ba274d..4b021d762 100644
--- a/packages/demobank-ui/src/route.ts
+++ b/packages/demobank-ui/src/route.ts
@@ -74,8 +74,8 @@ function findMatch<DEF, RM extends RouteMap<DEF>, ROUTES 
extends keyof RM>(
         found.groups === undefined ? {} : structuredClone(found.groups);
 
       Object.entries(params).forEach(([key, value]) => {
-        values[key] = value
-      })
+        values[key] = value;
+      });
 
       // @ts-expect-error values is a map string which is equivalent to the 
RouteParamsType
       return { name, parent: pagesMap, values };
@@ -90,7 +90,7 @@ export function useCurrentLocation<
   ROUTES extends keyof RM,
 >(pagesMap: RM) {
   const pageList = Object.keys(pagesMap) as Array<ROUTES>;
-  const { path, params } = useNavigationContext()
+  const { path, params } = useNavigationContext();
 
   return findMatch(pagesMap, pageList, path, params);
 }
diff --git a/packages/demobank-ui/src/utils.ts 
b/packages/demobank-ui/src/utils.ts
index 1d3650772..4413ce814 100644
--- a/packages/demobank-ui/src/utils.ts
+++ b/packages/demobank-ui/src/utils.ts
@@ -89,8 +89,7 @@ export type RecursivePartial<Type> = {
       : Type[P];
 };
 export type ErrorMessageMappingFor<Type> = {
-  [prop in keyof Type]+?: // enumerate known object
-  Exclude<Type[prop], undefined> extends PaytoString
+  [prop in keyof Type]+?: Exclude<Type[prop], undefined> extends PaytoString 
// enumerate known object
     ? TranslatedString
     : Exclude<Type[prop], undefined> extends AmountString
       ? TranslatedString

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