gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: search account in aml form an


From: gnunet
Subject: [taler-wallet-core] branch master updated: search account in aml form and remove name from dynamic forms
Date: Fri, 06 Sep 2024 18:55:05 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new c2efc802b search account in aml form and remove name from dynamic forms
c2efc802b is described below

commit c2efc802b2789cb47a6b0a54fc1672b98ee37db2
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Sep 6 13:54:33 2024 -0300

    search account in aml form and remove name from dynamic forms
---
 .../aml-backoffice-ui/src/ExchangeAmlFrame.tsx     |  12 +-
 packages/aml-backoffice-ui/src/Routing.tsx         |   6 +-
 packages/aml-backoffice-ui/src/forms/simplest.ts   |   9 +-
 packages/aml-backoffice-ui/src/hooks/form.ts       |  19 +-
 .../aml-backoffice-ui/src/pages/CaseUpdate.tsx     |   6 +-
 packages/aml-backoffice-ui/src/pages/Cases.tsx     | 151 ++++++-----
 .../aml-backoffice-ui/src/pages/CreateAccount.tsx  |  12 +-
 packages/aml-backoffice-ui/src/pages/Search.tsx    | 298 +++++++++++++++++++++
 .../src/pages/ShowConsolidated.tsx                 |  16 +-
 .../aml-backoffice-ui/src/pages/UnlockAccount.tsx  |  10 +-
 packages/kyc-ui/src/forms/nameAndBirthdate.ts      |  59 ++--
 packages/kyc-ui/src/forms/personal-info.ts         |   7 +-
 packages/kyc-ui/src/forms/simplest.ts              |   9 +-
 packages/web-util/src/forms/FormProvider.tsx       |   2 +-
 .../src/forms/InputAbsoluteTime.stories.tsx        |   3 +-
 .../web-util/src/forms/InputAmount.stories.tsx     |   3 +-
 packages/web-util/src/forms/InputArray.stories.tsx |   5 +-
 packages/web-util/src/forms/InputArray.tsx         |  10 +-
 .../src/forms/InputChoiceHorizontal.stories.tsx    |   3 +-
 .../src/forms/InputChoiceStacked.stories.tsx       |   3 +-
 packages/web-util/src/forms/InputFile.stories.tsx  |   3 +-
 .../web-util/src/forms/InputInteger.stories.tsx    |   3 +-
 packages/web-util/src/forms/InputLine.stories.tsx  |   3 +-
 .../src/forms/InputSelectMultiple.stories.tsx      |   6 +-
 .../web-util/src/forms/InputSelectOne.stories.tsx  |   3 +-
 packages/web-util/src/forms/InputText.stories.tsx  |   3 +-
 .../web-util/src/forms/InputTextArea.stories.tsx   |   3 +-
 .../web-util/src/forms/InputToggle.stories.tsx     |   3 +-
 packages/web-util/src/forms/forms.ts               |   6 +-
 packages/web-util/src/forms/ui-form.ts             |  11 +-
 30 files changed, 498 insertions(+), 189 deletions(-)

diff --git a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx 
b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx
index ca7f9b0b5..b7741d4c7 100644
--- a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx
+++ b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx
@@ -33,7 +33,12 @@ import {
   getLabelForPreferences,
   usePreferences,
 } from "./hooks/preferences.js";
-import { HomeIcon, PeopleIcon, ToInvestigateIcon } from "./pages/Cases.js";
+import {
+  HomeIcon,
+  PeopleIcon,
+  SearchIcon,
+  ToInvestigateIcon,
+} from "./pages/Cases.js";
 
 /**
  * mapping route to view
@@ -236,6 +241,11 @@ function Navigation(): VNode {
       label: i18n.str`Investigation`,
     },
     { route: privatePages.active, Icon: HomeIcon, label: i18n.str`Active` },
+    {
+      route: privatePages.search,
+      Icon: SearchIcon,
+      label: i18n.str`Search`,
+    },
   ];
   const { path } = useNavigationContext();
   return (
diff --git a/packages/aml-backoffice-ui/src/Routing.tsx 
b/packages/aml-backoffice-ui/src/Routing.tsx
index b99314889..c7f9a40fe 100644
--- a/packages/aml-backoffice-ui/src/Routing.tsx
+++ b/packages/aml-backoffice-ui/src/Routing.tsx
@@ -31,6 +31,7 @@ import { Officer } from "./pages/Officer.js";
 import { CaseDetails } from "./pages/CaseDetails.js";
 import { CaseUpdate, SelectForm } from "./pages/CaseUpdate.js";
 import { HandleAccountNotReady } from "./pages/HandleAccountNotReady.js";
+import { Search } from "./pages/Search.js";
 
 export function Routing(): VNode {
   const session = useOfficer();
@@ -95,6 +96,7 @@ function PublicRounting(): VNode {
 
 export const privatePages = {
   profile: urlPattern(/\/profile/, () => "#/profile"),
+  search: urlPattern(/\/search/, () => "#/search"),
   investigation: urlPattern(/\/investigation/, () => "#/investigation"),
   active: urlPattern(/\/active/, () => "#/active"),
   caseUpdate: urlPattern<{ cid: string; type: string }>(
@@ -116,7 +118,6 @@ function PrivateRouting(): VNode {
   const location = useCurrentLocation(privatePages);
   useEffect(() => {
     if (location.name === undefined) {
-      console.log("asd")
       navigateTo(privatePages.profile.url({}));
     }
   }, [location]);
@@ -145,6 +146,9 @@ function PrivateRouting(): VNode {
     case "active": {
       return <Cases />;
     }
+    case "search": {
+      return <Search />;
+    }
     default:
       assertUnreachable(location);
   }
diff --git a/packages/aml-backoffice-ui/src/forms/simplest.ts 
b/packages/aml-backoffice-ui/src/forms/simplest.ts
index 4cd781b74..215b0ba51 100644
--- a/packages/aml-backoffice-ui/src/forms/simplest.ts
+++ b/packages/aml-backoffice-ui/src/forms/simplest.ts
@@ -29,8 +29,7 @@ export const v1 = (i18n: InternationalizationAPI): 
DoubleColumnForm => ({
       fields: [
         {
           type: "textArea",
-          id: ".comment" as UIHandlerId,
-          name: "comment",
+          id: "comment" as UIHandlerId,
           label: i18n.str`Comment`,
         },
       ],
@@ -59,8 +58,7 @@ export function resolutionSection(
     fields: [
       {
         type: "choiceHorizontal",
-        id: ".state" as UIHandlerId,
-        name: "state",
+        id: "state" as UIHandlerId,
         label: i18n.str`New state`,
         converterId: "TalerExchangeApi.AmlState",
         choices: [
@@ -80,9 +78,8 @@ export function resolutionSection(
       },
       {
         type: "amount",
-        id: ".threshold" as UIHandlerId,
+        id: "threshold" as UIHandlerId,
         currency: "NETZBON",
-        name: "threshold",
         converterId: "Taler.Amount",
         label: i18n.str`New threshold`,
       },
diff --git a/packages/aml-backoffice-ui/src/hooks/form.ts 
b/packages/aml-backoffice-ui/src/hooks/form.ts
index 70b2db571..375dbb190 100644
--- a/packages/aml-backoffice-ui/src/hooks/form.ts
+++ b/packages/aml-backoffice-ui/src/hooks/form.ts
@@ -126,14 +126,14 @@ export function useFormState<T>(
   shape: Array<UIHandlerId>,
   defaultValue: RecursivePartial<FormValues<T>>,
   check: (f: RecursivePartial<FormValues<T>>) => FormStatus<T>,
-): [FormHandler<T>, FormStatus<T>] {
+): { handler: FormHandler<T>; status: FormStatus<T> } {
   const [form, updateForm] =
     useState<RecursivePartial<FormValues<T>>>(defaultValue);
 
   const status = check(form);
   const handler = constructFormHandler(shape, form, updateForm, status.errors);
 
-  return [handler, status];
+  return { handler, status };
 }
 
 interface Tree<T> extends Record<string, Tree<T> | T> {}
@@ -163,7 +163,10 @@ export function setValueDeeper(object: any, names: 
string[], value: any): any {
   if (object === undefined) {
     return undefinedIfEmpty({ [head]: setValueDeeper({}, rest, value) });
   }
-  return undefinedIfEmpty({ ...object, [head]: setValueDeeper(object[head] ?? 
{}, rest, value) });
+  return undefinedIfEmpty({
+    ...object,
+    [head]: setValueDeeper(object[head] ?? {}, rest, value),
+  });
 }
 
 export function getShapeFromFields(
@@ -179,10 +182,7 @@ export function getShapeFromFields(
       }
       shape.push(field.id);
     } else if (field.type === "group") {
-      Array.prototype.push.apply(
-        shape,
-        getShapeFromFields(field.fields),
-      );
+      Array.prototype.push.apply(shape, getShapeFromFields(field.fields));
     }
   });
   return shape;
@@ -204,10 +204,7 @@ export function getRequiredFields(
       }
       shape.push(field.id);
     } else if (field.type === "group") {
-      Array.prototype.push.apply(
-        shape,
-        getRequiredFields(field.fields),
-      );
+      Array.prototype.push.apply(shape, getRequiredFields(field.fields));
     }
   });
   return shape;
diff --git a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx 
b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
index 2708dba4c..87f1aed5f 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
@@ -117,7 +117,7 @@ export function CaseUpdate({
     );
   });
 
-  const [form, state] = useFormState<FormType>(shape, initial, (st) => {
+  const { handler, status } = useFormState<FormType>(shape, initial, (st) => {
     const partialErrors = undefinedIfEmpty<FormErrors<FormType>>({
       state: st.state === undefined ? i18n.str`required` : undefined,
       threshold: !st.threshold ? i18n.str`required` : undefined,
@@ -143,7 +143,7 @@ export function CaseUpdate({
     };
   });
 
-  const validatedForm = state.status !== "ok" ? undefined : state.result;
+  const validatedForm = status.status !== "ok" ? undefined : status.result;
 
   const submitHandler =
     validatedForm === undefined
@@ -224,7 +224,7 @@ export function CaseUpdate({
                       fields={convertUiField(
                         i18n,
                         section.fields,
-                        form,
+                        handler,
                         getConverterById,
                       )}
                     />
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx 
b/packages/aml-backoffice-ui/src/pages/Cases.tsx
index c229850b1..c7191332a 100644
--- a/packages/aml-backoffice-ui/src/pages/Cases.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx
@@ -21,22 +21,18 @@ import {
 } from "@gnu-taler/taler-util";
 import {
   Attention,
-  ErrorLoading,
-  InputChoiceHorizontal,
   Loading,
-  UIHandlerId,
-  amlStateConverter,
   useTranslationContext,
 } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
-import { useCurrentDecisions, useCurrentDecisionsUnderInvestigation } from 
"../hooks/decisions.js";
+import {
+  useCurrentDecisions,
+  useCurrentDecisionsUnderInvestigation,
+} from "../hooks/decisions.js";
 
 import { privatePages } from "../Routing.js";
-import { FormErrors, RecursivePartial, useFormState } from "../hooks/form.js";
-import { undefinedIfEmpty } from "./CreateAccount.js";
-import { Officer } from "./Officer.js";
 import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
-import { useState } from "preact/hooks";
+import { Officer } from "./Officer.js";
 
 type FormType = {
   // state: TalerExchangeApi.AmlState;
@@ -48,7 +44,7 @@ export function CasesUI({
   onNext,
   filtered,
 }: {
-  filtered: boolean,
+  filtered: boolean;
   onFirstPage?: () => void;
   onNext?: () => void;
   records: TalerExchangeApi.AmlDecision[];
@@ -93,17 +89,20 @@ export function CasesUI({
   return (
     <div>
       <div class="sm:flex sm:items-center">
-        {filtered ?
+        {filtered ? (
           <div class="px-2 sm:flex-auto">
             <h1 class="text-base font-semibold leading-6 text-gray-900">
               <i18n.Translate>Cases under investigation</i18n.Translate>
             </h1>
             <p class="mt-2 text-sm text-gray-700 w-80">
               <i18n.Translate>
-                A list of all the accounts which are waiting for a deicison to 
be made.
+                A list of all the accounts which are waiting for a deicison to
+                be made.
               </i18n.Translate>
             </p>
-          </div> : <div class="px-2 sm:flex-auto">
+          </div>
+        ) : (
+          <div class="px-2 sm:flex-auto">
             <h1 class="text-base font-semibold leading-6 text-gray-900">
               <i18n.Translate>Cases</i18n.Translate>
             </h1>
@@ -113,7 +112,7 @@ export function CasesUI({
               </i18n.Translate>
             </p>
           </div>
-        }
+        )}
       </div>
       <div class="mt-8 flow-root">
         <div class="overflow-x-auto">
@@ -155,7 +154,11 @@ export function CasesUI({
                           </div>
                         </td>
                         <td class="whitespace-nowrap px-3 py-5 text-sm 
text-gray-900">
-                          {r.to_investigate ? <span title="require 
investigation"><ToInvestigateIcon /></span> : undefined}
+                          {r.to_investigate ? (
+                            <span title="require investigation">
+                              <ToInvestigateIcon />
+                            </span>
+                          ) : undefined}
                         </td>
                       </tr>
                     );
@@ -189,7 +192,8 @@ export function Cases() {
           <Fragment>
             <Attention type="danger" title={i18n.str`Operation denied`}>
               <i18n.Translate>
-                This account signature is wrong, contact administrator or 
create a new one.
+                This account signature is wrong, contact administrator or 
create
+                a new one.
               </i18n.Translate>
             </Attention>
             <Officer />
@@ -200,27 +204,26 @@ export function Cases() {
         return (
           <Fragment>
             <Attention type="danger" title={i18n.str`Operation denied`}>
-              <i18n.Translate>
-                This account is not known.
-              </i18n.Translate>
-            </Attention>
-            <Officer />
-          </Fragment>
-        );
-      }
-      case HttpStatusCode.Conflict: {
-        return (
-          <Fragment>
-            <Attention type="danger" title={i18n.str`Operation denied`}>
-              <i18n.Translate>
-                This account doesn't have access. Request account activation
-                sending your public key.
-              </i18n.Translate>
+              <i18n.Translate>This account is not known.</i18n.Translate>
             </Attention>
             <Officer />
           </Fragment>
         );
       }
+      case HttpStatusCode.Conflict:
+        {
+          return (
+            <Fragment>
+              <Attention type="danger" title={i18n.str`Operation denied`}>
+                <i18n.Translate>
+                  This account doesn't have access. Request account activation
+                  sending your public key.
+                </i18n.Translate>
+              </Attention>
+              <Officer />
+            </Fragment>
+          );
+        }
         return <Officer />;
       default:
         assertUnreachable(list);
@@ -233,10 +236,10 @@ export function Cases() {
       records={list.body}
       onFirstPage={list.isFirstPage ? undefined : list.loadFirst}
       onNext={list.isLastPage ? undefined : list.loadNext}
-    // filter={stateFilter}
-    // onChangeFilter={(d) => {
-    //   setStateFilter(d);
-    // }}
+      // filter={stateFilter}
+      // onChangeFilter={(d) => {
+      //   setStateFilter(d);
+      // }}
     />
   );
 }
@@ -258,7 +261,8 @@ export function CasesUnderInvestigation() {
           <Fragment>
             <Attention type="danger" title={i18n.str`Operation denied`}>
               <i18n.Translate>
-                This account signature is wrong, contact administrator or 
create a new one.
+                This account signature is wrong, contact administrator or 
create
+                a new one.
               </i18n.Translate>
             </Attention>
             <Officer />
@@ -269,27 +273,26 @@ export function CasesUnderInvestigation() {
         return (
           <Fragment>
             <Attention type="danger" title={i18n.str`Operation denied`}>
-              <i18n.Translate>
-                This account is not known.
-              </i18n.Translate>
-            </Attention>
-            <Officer />
-          </Fragment>
-        );
-      }
-      case HttpStatusCode.Conflict: {
-        return (
-          <Fragment>
-            <Attention type="danger" title={i18n.str`Operation denied`}>
-              <i18n.Translate>
-                This account doesn't have access. Request account activation
-                sending your public key.
-              </i18n.Translate>
+              <i18n.Translate>This account is not known.</i18n.Translate>
             </Attention>
             <Officer />
           </Fragment>
         );
       }
+      case HttpStatusCode.Conflict:
+        {
+          return (
+            <Fragment>
+              <Attention type="danger" title={i18n.str`Operation denied`}>
+                <i18n.Translate>
+                  This account doesn't have access. Request account activation
+                  sending your public key.
+                </i18n.Translate>
+              </Attention>
+              <Officer />
+            </Fragment>
+          );
+        }
         return <Officer />;
       default:
         assertUnreachable(list);
@@ -302,10 +305,10 @@ export function CasesUnderInvestigation() {
       records={list.body}
       onFirstPage={list.isFirstPage ? undefined : list.loadFirst}
       onNext={list.isLastPage ? undefined : list.loadNext}
-    // filter={stateFilter}
-    // onChangeFilter={(d) => {
-    //   setStateFilter(d);
-    // }}
+      // filter={stateFilter}
+      // onChangeFilter={(d) => {
+      //   setStateFilter(d);
+      // }}
     />
   );
 }
@@ -316,12 +319,23 @@ export function CasesUnderInvestigation() {
 //   </svg>
 // }
 export const ToInvestigateIcon = () => (
-  <svg title="requires investigation" xmlns="http://www.w3.org/2000/svg"; 
fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" 
class="size-6 w-6">
-    <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 
3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 
1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 
15.75h.007v.008H12v-.008Z" />
+  <svg
+    title="requires investigation"
+    xmlns="http://www.w3.org/2000/svg";
+    fill="none"
+    viewBox="0 0 24 24"
+    stroke-width="1.5"
+    stroke="currentColor"
+    class="size-6 w-6"
+  >
+    <path
+      stroke-linecap="round"
+      stroke-linejoin="round"
+      d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 
2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 
16.126ZM12 15.75h.007v.008H12v-.008Z"
+    />
   </svg>
 );
 
-
 export const PeopleIcon = () => (
   <svg
     xmlns="http://www.w3.org/2000/svg";
@@ -356,6 +370,23 @@ export const HomeIcon = () => (
   </svg>
 );
 
+export const SearchIcon = () => (
+  <svg
+    xmlns="http://www.w3.org/2000/svg";
+    fill="none"
+    viewBox="0 0 24 24"
+    stroke-width="1.5"
+    stroke="currentColor"
+    class="w-6 h-6"
+  >
+    <path
+      stroke-linecap="round"
+      stroke-linejoin="round"
+      d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 
10.607Z"
+    />
+  </svg>
+);
+
 function Pagination({
   onFirstPage,
   onNext,
diff --git a/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx 
b/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx
index 87310aa27..328d8459b 100644
--- a/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx
@@ -89,7 +89,9 @@ function createFormValidator(
   };
 }
 
-export function undefinedIfEmpty<T extends object | undefined>(obj: T): T | 
undefined {
+export function undefinedIfEmpty<T extends object | undefined>(
+  obj: T,
+): T | undefined {
   if (obj === undefined) return undefined;
   return Object.keys(obj).some(
     (k) => (obj as Record<string, T>)[k] !== undefined,
@@ -105,7 +107,7 @@ export function CreateAccount(): VNode {
 
   const [notification, withErrorHandler] = useLocalNotificationHandler();
 
-  const [form, status] = useFormState<FormType>(
+  const { handler, status } = useFormState<FormType>(
     [".password", ".repeat"] as Array<UIHandlerId>,
     {
       password: undefined,
@@ -118,7 +120,7 @@ export function CreateAccount(): VNode {
     status.status === "fail" || officer.state !== "not-found"
       ? undefined
       : withErrorHandler(
-          async () => officer.create(form.password!.value!),
+          async () => officer.create(handler.password!.value!),
           () => {},
         );
   return (
@@ -148,7 +150,7 @@ export function CreateAccount(): VNode {
                 name="password"
                 type="password"
                 required
-                handler={form.password}
+                handler={handler.password}
               />
             </div>
 
@@ -158,7 +160,7 @@ export function CreateAccount(): VNode {
                 name="repeat"
                 type="password"
                 required
-                handler={form.repeat}
+                handler={handler.repeat}
               />
             </div>
 
diff --git a/packages/aml-backoffice-ui/src/pages/Search.tsx 
b/packages/aml-backoffice-ui/src/pages/Search.tsx
new file mode 100644
index 000000000..047e56180
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/pages/Search.tsx
@@ -0,0 +1,298 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022-2024 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 {
+  convertUiField,
+  getConverterById,
+  InternationalizationAPI,
+  RenderAllFieldsByUiConfig,
+  UIFormElementConfig,
+  UIHandlerId,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { h } from "preact";
+import {
+  FormErrors,
+  FormStatus,
+  FormValues,
+  getShapeFromFields,
+  RecursivePartial,
+  useFormState,
+} from "../hooks/form.js";
+import { useOfficer } from "../hooks/officer.js";
+import { undefinedIfEmpty } from "./CreateAccount.js";
+import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
+import { TranslatedString } from "@gnu-taler/taler-util";
+
+interface FormType {
+  paytoType: "generic" | "iban" | "x-taler-bank";
+}
+
+export function Search() {
+  const officer = useOfficer();
+  const { i18n } = useTranslationContext();
+
+  const paytoForm = useFormState(
+    getShapeFromFields(paytoTypeField(i18n)),
+    { paytoType: "generic" },
+    createFormValidator(i18n),
+  );
+
+  const secondFieldSet =
+    paytoForm.status.status !== "ok"
+      ? []
+      : paytoForm.status.result.paytoType === "iban"
+        ? ibanFields(i18n)
+        : paytoForm.status.result.paytoType === "x-taler-bank"
+          ? talerBankFields(i18n)
+          : genericFields(i18n);
+
+  const secondForm = useFormState(
+    getShapeFromFields(secondFieldSet),
+    {},
+    createFormValidator(i18n),
+  );
+
+  if (officer.state !== "ready") {
+    return <HandleAccountNotReady officer={officer} />;
+  }
+
+  return (
+    <div>
+      <h1 class="my-2 text-3xl font-bold tracking-tight text-gray-900 ">
+        <i18n.Translate>Search account</i18n.Translate>
+      </h1>
+      <form
+        class="space-y-6"
+        noValidate
+        onSubmit={(e) => {
+          e.preventDefault();
+        }}
+        autoCapitalize="none"
+        autoCorrect="off"
+      >
+        <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3">
+          <RenderAllFieldsByUiConfig
+            fields={convertUiField(
+              i18n,
+              paytoTypeField(i18n),
+              paytoForm.handler,
+              getConverterById,
+            )}
+          />
+        </div>
+      </form>
+
+      <form
+        class="space-y-6"
+        noValidate
+        onSubmit={(e) => {
+          e.preventDefault();
+        }}
+        autoCapitalize="none"
+        autoCorrect="off"
+      >
+        <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3">
+          <RenderAllFieldsByUiConfig
+            fields={convertUiField(
+              i18n,
+              secondFieldSet,
+              secondForm.handler,
+              getConverterById,
+            )}
+          />
+        </div>
+      </form>
+    </div>
+  );
+}
+
+function createFormValidator(i18n: InternationalizationAPI) {
+  return function check(
+    state: RecursivePartial<FormValues<FormType>>,
+  ): FormStatus<FormType> {
+    const errors = undefinedIfEmpty<FormErrors<FormType>>({
+      paytoType: !state?.paytoType ? i18n.str`required` : undefined,
+    });
+
+    if (errors === undefined) {
+      const result: FormType = {
+        paytoType: state.paytoType! as any,
+      };
+      return {
+        status: "ok",
+        result,
+        errors,
+      };
+    }
+    const result: RecursivePartial<FormType> = {
+      paytoType: state?.paytoType,
+    };
+    return {
+      status: "fail",
+      result,
+      errors,
+    };
+  };
+}
+
+const paytoTypeField: (
+  i18n: InternationalizationAPI,
+) => UIFormElementConfig[] = (i18n) => [
+  {
+    id: "paytoType" as UIHandlerId,
+    type: "choiceHorizontal",
+    required: true,
+    choices: [
+      {
+        value: "generic",
+        label: i18n.str`Generic Payto:// URI`,
+      },
+      {
+        value: "iban",
+        label: i18n.str`IBAN`,
+      },
+      {
+        value: "x-taler-bank",
+        label: i18n.str`Taler Bank`,
+      },
+    ],
+    label: `Account type`,
+  },
+];
+
+const receiverName: (i18n: InternationalizationAPI) => UIFormElementConfig = (
+  i18n,
+) => ({
+  id: "receiverName" as UIHandlerId,
+  type: "text",
+  required: true,
+  label: `Owner's name`,
+  help: i18n.str`It should match the bank account name.`,
+  placeholder: i18n.str`John Doe`,
+});
+
+const genericFields: (
+  i18n: InternationalizationAPI,
+) => UIFormElementConfig[] = (i18n) => [
+  {
+    id: "paytoText" as UIHandlerId,
+    type: "textArea",
+    required: true,
+    label: `Payto URI`,
+    help: i18n.str`As defined by RFC 8905`,
+    placeholder: i18n.str`payto://`,
+  },
+  receiverName(i18n),
+];
+const ibanFields: (i18n: InternationalizationAPI) => UIFormElementConfig[] = (
+  i18n,
+) => [
+  {
+    id: "account" as UIHandlerId,
+    type: "text",
+    required: true,
+    label: `Account`,
+    help: i18n.str`International Bank Account Number`,
+    placeholder: i18n.str`DE1231231231`,
+    validator: (value) => validateIBAN(value, i18n),
+  },
+  receiverName(i18n),
+];
+
+const talerBankFields: (
+  i18n: InternationalizationAPI,
+) => UIFormElementConfig[] = (i18n) => [
+  {
+    id: "account" as UIHandlerId,
+    type: "text",
+    required: true,
+    label: `Bank account`,
+    help: i18n.str`Bank account id`,
+    placeholder: i18n.str`DE123123123`,
+  },
+  {
+    id: "hostname" as UIHandlerId,
+    type: "text",
+    required: true,
+    label: `Hostname`,
+    validator: (value) => validateTalerBank(value, i18n),
+    help: i18n.str`Without the scheme, may include subpath: bank.com, 
bank.com/path/`,
+    placeholder: i18n.str`bank.demo.taler.net`,
+  },
+  receiverName(i18n),
+];
+
+function validateIBAN(
+  iban: string,
+  i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): TranslatedString | undefined {
+  // Check total length
+  if (iban.length < 4)
+    return i18n.str`IBAN numbers usually have more that 4 digits`;
+  if (iban.length > 34)
+    return i18n.str`IBAN numbers usually have less that 34 digits`;
+
+  const A_code = "A".charCodeAt(0);
+  const Z_code = "Z".charCodeAt(0);
+  const IBAN = iban.toUpperCase();
+
+  // check supported country
+  // const code = IBAN.substr(0, 2);
+  // const found = code in COUNTRY_TABLE;
+  // if (!found) return i18n.str`IBAN country code not found`;
+
+  // 2.- Move the four initial characters to the end of the string
+  const step2 = IBAN.substr(4) + iban.substr(0, 4);
+  const step3 = Array.from(step2)
+    .map((letter) => {
+      const code = letter.charCodeAt(0);
+      if (code < A_code || code > Z_code) return letter;
+      return `${letter.charCodeAt(0) - "A".charCodeAt(0) + 10}`;
+    })
+    .join("");
+
+  function calculate_iban_checksum(str: string): number {
+    const numberStr = str.substr(0, 5);
+    const rest = str.substr(5);
+    const number = parseInt(numberStr, 10);
+    const result = number % 97;
+    if (rest.length > 0) {
+      return calculate_iban_checksum(`${result}${rest}`);
+    }
+    return result;
+  }
+
+  const checksum = calculate_iban_checksum(step3);
+  if (checksum !== 1)
+    return i18n.str`IBAN number is invalid, checksum is wrong`;
+  return undefined;
+}
+
+const DOMAIN_REGEX =
+  
/^[a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9-_](?:\.[a-zA-Z0-9-_]{2,})+(:[0-9]+)?(\/[a-zA-Z0-9-.]+)*\/?$/;
+
+function validateTalerBank(
+  addr: string,
+  i18n: InternationalizationAPI,
+): TranslatedString | undefined {
+  try {
+    const valid = DOMAIN_REGEX.test(addr);
+    if (valid) return undefined;
+  } catch (e) {
+    console.log(e);
+  }
+  return i18n.str`This is not a valid host.`;
+}
diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx 
b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
index 21c14fee3..7374125b0 100644
--- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
+++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
@@ -20,7 +20,6 @@ import {
   TranslatedString,
 } from "@gnu-taler/taler-util";
 import {
-  DefaultForm,
   FormConfiguration,
   RenderAllFieldsByUiConfig,
   UIFormElementConfig,
@@ -31,8 +30,8 @@ import {
 } from "@gnu-taler/web-util/browser";
 import { format } from "date-fns";
 import { Fragment, VNode, h } from "preact";
-import { AmlEvent } from "./CaseDetails.js";
 import { getShapeFromFields, useFormState } from "../hooks/form.js";
+import { AmlEvent } from "./CaseDetails.js";
 
 /**
  * the exchange doesn't hava a consistent api
@@ -78,7 +77,6 @@ export function ShowConsolidated({
                 type: "text",
                 label: key as TranslatedString,
                 id: `${key}.value` as UIHandlerId,
-                name: `${key}.value`,
                 disabled: true,
                 help: `At ${
                   field.since.t_ms === "never"
@@ -92,13 +90,11 @@ export function ShowConsolidated({
         : undefined!,
     ],
   };
-  const shape: Array<UIHandlerId> = [];
-
-  formConfig.design.forEach((section) => {
-    Array.prototype.push.apply(shape, getShapeFromFields(section.fields));
-  });
+  const shape: Array<UIHandlerId> = formConfig.design.flatMap((field) =>
+    getShapeFromFields(field.fields),
+  );
 
-  const [form, state] = useFormState<{}>(shape, fixed, (result) => {
+  const { handler } = useFormState<{}>(shape, fixed, (result) => {
     return { status: "ok", errors: undefined, result };
   });
 
@@ -130,7 +126,7 @@ export function ShowConsolidated({
                       fields={convertUiField(
                         i18n,
                         section.fields,
-                        form,
+                        handler,
                         getConverterById,
                       )}
                     />
diff --git a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx 
b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
index 084e639bf..72656bb98 100644
--- a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
+++ b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
@@ -19,7 +19,7 @@ import {
   LocalNotificationBanner,
   UIHandlerId,
   useLocalNotificationHandler,
-  useTranslationContext
+  useTranslationContext,
 } from "@gnu-taler/web-util/browser";
 import { VNode, h } from "preact";
 import { FormErrors, useFormState } from "../hooks/form.js";
@@ -36,7 +36,7 @@ export function UnlockAccount(): VNode {
   const officer = useOfficer();
   const [notification, withErrorHandler] = useLocalNotificationHandler();
 
-  const [form, status] = useFormState<FormType>(
+  const { handler, status } = useFormState<FormType>(
     [".password"] as Array<UIHandlerId>,
     {
       password: undefined,
@@ -64,7 +64,7 @@ export function UnlockAccount(): VNode {
     status.status === "fail" || officer.state !== "locked"
       ? undefined
       : withErrorHandler(
-          async () => officer.tryUnlock(form.password!.value!),
+          async () => officer.tryUnlock(handler.password!.value!),
           () => {},
         );
 
@@ -94,14 +94,13 @@ export function UnlockAccount(): VNode {
 
       <div class="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px] ">
         <div class="bg-gray-100 px-6 py-6 shadow sm:rounded-lg sm:px-12">
-
           <div class="mb-4">
             <InputLine<FormType, "password">
               label={i18n.str`Password`}
               name="password"
               type="password"
               required
-              handler={form.password}
+              handler={handler.password}
             />
           </div>
 
@@ -115,7 +114,6 @@ export function UnlockAccount(): VNode {
               <i18n.Translate>Unlock</i18n.Translate>
             </Button>
           </div>
-
         </div>
         <Button
           type="button"
diff --git a/packages/kyc-ui/src/forms/nameAndBirthdate.ts 
b/packages/kyc-ui/src/forms/nameAndBirthdate.ts
index 4e4cb17e6..dc4aa52e5 100644
--- a/packages/kyc-ui/src/forms/nameAndBirthdate.ts
+++ b/packages/kyc-ui/src/forms/nameAndBirthdate.ts
@@ -14,34 +14,31 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
- import type {
-    DoubleColumnForm,
-    DoubleColumnFormSection,
-    InternationalizationAPI,
-    UIHandlerId,
-  } from "@gnu-taler/web-util/browser";
-  
-  export const nameAndDob = (i18n: InternationalizationAPI): DoubleColumnForm 
=> ({
-    type: "double-column" as const,
-    design: [
-      {
-        title: i18n.str`Simple form`,
-        fields: [
-          {
-            type: "textArea",
-            id: ".full_name" as UIHandlerId,
-            name: "full_name",
-            label: i18n.str`Full Name`,
-          },
-          {
-            type: "textArea",
-            id: ".birthdate" as UIHandlerId,
-            name: "birthdate",
-            label: i18n.str`Birthdate`,
-          },
-        ],
-      },
-    ],
-  });
-  
-  
\ No newline at end of file
+import type {
+  DoubleColumnForm,
+  InternationalizationAPI,
+  UIHandlerId,
+} from "@gnu-taler/web-util/browser";
+
+export const nameAndDob = (
+  i18n: InternationalizationAPI,
+): DoubleColumnForm => ({
+  type: "double-column" as const,
+  design: [
+    {
+      title: i18n.str`Simple form`,
+      fields: [
+        {
+          type: "textArea",
+          id: "full_name" as UIHandlerId,
+          label: i18n.str`Full Name`,
+        },
+        {
+          type: "textArea",
+          id: "birthdate" as UIHandlerId,
+          label: i18n.str`Birthdate`,
+        },
+      ],
+    },
+  ],
+});
diff --git a/packages/kyc-ui/src/forms/personal-info.ts 
b/packages/kyc-ui/src/forms/personal-info.ts
index 657fe603f..799a8eb3a 100644
--- a/packages/kyc-ui/src/forms/personal-info.ts
+++ b/packages/kyc-ui/src/forms/personal-info.ts
@@ -16,7 +16,6 @@
 
 import type {
   DoubleColumnForm,
-  DoubleColumnFormSection,
   InternationalizationAPI,
   UIHandlerId,
 } from "@gnu-taler/web-util/browser";
@@ -40,8 +39,7 @@ export const personalInfo = (
         // },
         {
           type: "choiceStacked",
-          name: "trucker",
-          id: ".trucker" as UIHandlerId,
+          id: "trucker" as UIHandlerId,
           required: true,
           label: i18n.str`Are you a cross-border truck driver?`,
           choices: [
@@ -57,9 +55,8 @@ export const personalInfo = (
         },
         {
           type: "amount",
-          id: ".money" as UIHandlerId,
+          id: "money" as UIHandlerId,
           currency: "YEIN",
-          name: "money",
           converterId: "Taler.Amount",
           label: i18n.str`How much is in your pockets?`,
         },
diff --git a/packages/kyc-ui/src/forms/simplest.ts 
b/packages/kyc-ui/src/forms/simplest.ts
index aa0646959..9cadbc95c 100644
--- a/packages/kyc-ui/src/forms/simplest.ts
+++ b/packages/kyc-ui/src/forms/simplest.ts
@@ -29,8 +29,7 @@ export const simplest = (i18n: InternationalizationAPI): 
DoubleColumnForm => ({
       fields: [
         {
           type: "textArea",
-          id: ".comment" as UIHandlerId,
-          name: "comment",
+          id: "comment" as UIHandlerId,
           label: i18n.str`Comment`,
         },
       ],
@@ -47,8 +46,7 @@ export function resolutionSection(
     fields: [
       {
         type: "choiceHorizontal",
-        id: ".state" as UIHandlerId,
-        name: "state",
+        id: "state" as UIHandlerId,
         label: i18n.str`New state`,
         converterId: "TalerExchangeApi.AmlState",
         choices: [
@@ -68,9 +66,8 @@ export function resolutionSection(
       },
       {
         type: "amount",
-        id: ".threshold" as UIHandlerId,
+        id: "threshold" as UIHandlerId,
         currency: "NETZBON",
-        name: "threshold",
         converterId: "Taler.Amount",
         label: i18n.str`New threshold`,
       },
diff --git a/packages/web-util/src/forms/FormProvider.tsx 
b/packages/web-util/src/forms/FormProvider.tsx
index 5e08efb32..fe886030a 100644
--- a/packages/web-util/src/forms/FormProvider.tsx
+++ b/packages/web-util/src/forms/FormProvider.tsx
@@ -14,7 +14,7 @@ export interface FormType<T extends object> {
   computeFormState?: (v: Partial<T>) => FormState<T>;
 }
 
-export const FormContext = createContext<FormType<any>| undefined>(undefined);
+export const FormContext = createContext<FormType<any> | undefined>(undefined);
 
 /**
  * Map of {[field]:FieldUIOptions}
diff --git a/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx 
b/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx
index dcaf1cec9..2f67f952f 100644
--- a/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx
+++ b/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "absoluteTimeText",
           label: "label of the field" as TranslatedString,
-          id: ".today" as UIHandlerId,
-          name: "today",
+          id: "today" as UIHandlerId,
           pattern: "dd/MM/yyyy HH:mm",
         },
       ],
diff --git a/packages/web-util/src/forms/InputAmount.stories.tsx 
b/packages/web-util/src/forms/InputAmount.stories.tsx
index 052b22813..425824b75 100644
--- a/packages/web-util/src/forms/InputAmount.stories.tsx
+++ b/packages/web-util/src/forms/InputAmount.stories.tsx
@@ -52,9 +52,8 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "amount",
           label: "label of the field" as TranslatedString,
-          id: ".amount" as UIHandlerId,
+          id: "amount" as UIHandlerId,
           currency: "ARS",
-          name: "amount",
         },
       ],
     },
diff --git a/packages/web-util/src/forms/InputArray.stories.tsx 
b/packages/web-util/src/forms/InputArray.stories.tsx
index 31bad66a4..558e2e2aa 100644
--- a/packages/web-util/src/forms/InputArray.stories.tsx
+++ b/packages/web-util/src/forms/InputArray.stories.tsx
@@ -60,10 +60,9 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "array",
           label: "People" as TranslatedString,
-          name: "comment",
           fields: [],
-          id: ".name" as UIHandlerId,
-          labelFieldId: "name" as UIHandlerId,
+          id: "name" as UIHandlerId,
+          labelFieldId: "ame" as UIHandlerId,
         },
       ],
     },
diff --git a/packages/web-util/src/forms/InputArray.tsx 
b/packages/web-util/src/forms/InputArray.tsx
index d90028508..58f403035 100644
--- a/packages/web-util/src/forms/InputArray.tsx
+++ b/packages/web-util/src/forms/InputArray.tsx
@@ -99,7 +99,7 @@ export function InputArray<T extends object, K extends keyof 
T>(
   const [selectedIndex, setSelected] = useState<number | undefined>(undefined);
   const selected =
     selectedIndex === undefined ? undefined : list[selectedIndex];
-    
+
   return (
     <div class="sm:col-span-6">
       <LabelWithTooltipMaybeRequired
@@ -110,7 +110,7 @@ export function InputArray<T extends object, K extends 
keyof T>(
 
       <div class="-space-y-px rounded-md bg-white ">
         {list.map((v, idx) => {
-          const label = getValueDeeper(v, labelField.split("."))
+          const label = getValueDeeper(v, labelField.split("."));
           return (
             <Option
               label={label as TranslatedString}
@@ -204,8 +204,6 @@ export function InputArray<T extends object, K extends 
keyof T>(
   );
 }
 
-
-
 export function getValueDeeper(
   object: Record<string, any>,
   names: string[],
@@ -218,9 +216,7 @@ export function getValueDeeper(
     return getValueDeeper(object, rest);
   }
   if (object === undefined) {
-    return ""
+    return "";
   }
   return getValueDeeper(object[head], rest);
 }
-
-
diff --git a/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx 
b/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx
index 4d3745fe5..1de160605 100644
--- a/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx
+++ b/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "choiceHorizontal",
           label: "label of the field" as TranslatedString,
-          id: ".commnet" as UIHandlerId,
-          name: "comment",
+          id: "commnet" as UIHandlerId,
           choices: [
             {
               label: "first choice" as TranslatedString,
diff --git a/packages/web-util/src/forms/InputChoiceStacked.stories.tsx 
b/packages/web-util/src/forms/InputChoiceStacked.stories.tsx
index 8d57b3689..5ee893b96 100644
--- a/packages/web-util/src/forms/InputChoiceStacked.stories.tsx
+++ b/packages/web-util/src/forms/InputChoiceStacked.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "choiceStacked",
           label: "label of the field" as TranslatedString,
-          name: "comment",
-          id: ".comment" as UIHandlerId,
+          id: "comment" as UIHandlerId,
           choices: [
             {
               label: "first choice" as TranslatedString,
diff --git a/packages/web-util/src/forms/InputFile.stories.tsx 
b/packages/web-util/src/forms/InputFile.stories.tsx
index 591b4e2af..58fb16835 100644
--- a/packages/web-util/src/forms/InputFile.stories.tsx
+++ b/packages/web-util/src/forms/InputFile.stories.tsx
@@ -52,9 +52,8 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "file",
           label: "label of the field" as TranslatedString,
-          name: "comment",
           required: true,
-          id: ".comment" as UIHandlerId,
+          id: "comment" as UIHandlerId,
           accept: ".png",
           tooltip:
             "this is a very long tooltip that explain what the field does 
without being short" as TranslatedString,
diff --git a/packages/web-util/src/forms/InputInteger.stories.tsx 
b/packages/web-util/src/forms/InputInteger.stories.tsx
index e6b78c242..fd7fc39ed 100644
--- a/packages/web-util/src/forms/InputInteger.stories.tsx
+++ b/packages/web-util/src/forms/InputInteger.stories.tsx
@@ -46,8 +46,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "integer",
           label: "label of the field" as TranslatedString,
-          name: "age",
-          id: ".comment" as UIHandlerId,
+          id: "comment" as UIHandlerId,
           tooltip: "just numbers" as TranslatedString,
         },
       ],
diff --git a/packages/web-util/src/forms/InputLine.stories.tsx 
b/packages/web-util/src/forms/InputLine.stories.tsx
index 16530ff2b..32b26329b 100644
--- a/packages/web-util/src/forms/InputLine.stories.tsx
+++ b/packages/web-util/src/forms/InputLine.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "text",
           label: "label of the field" as TranslatedString,
-          name: "comment",
-          id: ".comment" as UIHandlerId,
+          id: "comment" as UIHandlerId,
         },
       ],
     },
diff --git a/packages/web-util/src/forms/InputSelectMultiple.stories.tsx 
b/packages/web-util/src/forms/InputSelectMultiple.stories.tsx
index a85259786..210ab1b2b 100644
--- a/packages/web-util/src/forms/InputSelectMultiple.stories.tsx
+++ b/packages/web-util/src/forms/InputSelectMultiple.stories.tsx
@@ -54,8 +54,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "selectMultiple",
           label: "allow diplicates" as TranslatedString,
-          name: "pets",
-          id: ".pets" as UIHandlerId,
+          id: "pets" as UIHandlerId,
           placeholder: "search..." as TranslatedString,
           choices: [
             {
@@ -75,8 +74,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "selectMultiple",
           label: "unique values" as TranslatedString,
-          name: "things",
-          id: ".things" as UIHandlerId,
+          id: "things" as UIHandlerId,
           unique: true,
           placeholder: "search..." as TranslatedString,
           choices: [
diff --git a/packages/web-util/src/forms/InputSelectOne.stories.tsx 
b/packages/web-util/src/forms/InputSelectOne.stories.tsx
index f6b2354c5..56284f4ab 100644
--- a/packages/web-util/src/forms/InputSelectOne.stories.tsx
+++ b/packages/web-util/src/forms/InputSelectOne.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "selectOne",
           label: "label of the field" as TranslatedString,
-          name: "things",
-          id: ".things" as UIHandlerId,
+          id: "things" as UIHandlerId,
           placeholder: "search..." as TranslatedString,
           choices: [
             {
diff --git a/packages/web-util/src/forms/InputText.stories.tsx 
b/packages/web-util/src/forms/InputText.stories.tsx
index 8e2b415ac..3fa171655 100644
--- a/packages/web-util/src/forms/InputText.stories.tsx
+++ b/packages/web-util/src/forms/InputText.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "text",
           label: "label of the field" as TranslatedString,
-          id: ".comment" as UIHandlerId,
-          name: "comment",
+          id: "comment" as UIHandlerId,
         },
       ],
     },
diff --git a/packages/web-util/src/forms/InputTextArea.stories.tsx 
b/packages/web-util/src/forms/InputTextArea.stories.tsx
index d36e87fc5..c3df4f186 100644
--- a/packages/web-util/src/forms/InputTextArea.stories.tsx
+++ b/packages/web-util/src/forms/InputTextArea.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "text",
           label: "label of the field" as TranslatedString,
-          id: ".comment" as UIHandlerId,
-          name: "comment",
+          id: "comment" as UIHandlerId,
         },
       ],
     },
diff --git a/packages/web-util/src/forms/InputToggle.stories.tsx 
b/packages/web-util/src/forms/InputToggle.stories.tsx
index ae9161645..7ce3cec5a 100644
--- a/packages/web-util/src/forms/InputToggle.stories.tsx
+++ b/packages/web-util/src/forms/InputToggle.stories.tsx
@@ -52,8 +52,7 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
         {
           type: "toggle",
           label: "label of the field" as TranslatedString,
-          name: "comment",
-          id: ".comment" as UIHandlerId,
+          id: "comment" as UIHandlerId,
         },
       ],
     },
diff --git a/packages/web-util/src/forms/forms.ts 
b/packages/web-util/src/forms/forms.ts
index b37363a62..3b56081ef 100644
--- a/packages/web-util/src/forms/forms.ts
+++ b/packages/web-util/src/forms/forms.ts
@@ -334,12 +334,13 @@ function converInputFieldsProps(
   p: UIFormFieldBaseConfig,
   getConverterById: GetConverterById,
 ) {
+  const names = p.id.split(".");
   return {
     converter: getConverterById(p.converterId, p),
-    handler: getValueDeeper2(form, p.id.split(".")),
-    name: p.name,
+    handler: getValueDeeper2(form, names),
     required: p.required,
     disabled: p.disabled,
+    name: names[names.length - 1],
     help: p.help,
     placeholder: p.placeholder,
     tooltip: p.tooltip,
@@ -355,7 +356,6 @@ function converBaseFieldsProps(
     after: getAddonById(p.addonAfterId),
     before: getAddonById(p.addonBeforeId),
     hidden: p.hidden,
-    name: p.name,
     help: i18n_.str`${p.help}`,
     label: i18n_.str`${p.label}`,
     tooltip: i18n_.str`${p.tooltip}`,
diff --git a/packages/web-util/src/forms/ui-form.ts 
b/packages/web-util/src/forms/ui-form.ts
index 012499d6d..f26e08f3b 100644
--- a/packages/web-util/src/forms/ui-form.ts
+++ b/packages/web-util/src/forms/ui-form.ts
@@ -12,7 +12,9 @@ import {
   codecOptional,
   Integer,
   TalerProtocolTimestamp,
+  TranslatedString,
 } from "@gnu-taler/taler-util";
+import { InternationalizationAPI } from "../index.browser.js";
 
 export type FormConfiguration = DoubleColumnForm;
 
@@ -134,9 +136,6 @@ export type UIFieldElementDescription = {
   /* short text to be shown close to the field, usually below and dimmer*/
   help?: string;
 
-  /* name of the field, useful for a11y */
-  name: string;
-
   /* if the field should be initially hidden */
   hidden?: boolean;
 
@@ -162,6 +161,11 @@ export type UIFormFieldBaseConfig = 
UIFieldElementDescription & {
    */
   converterId?: string;
 
+  /* return an error message if the value is not valid, returns un undefined
+   if there is no error
+   */
+  validator?: (value: string) => TranslatedString | undefined;
+
   /* property id of the form */
   id: UIHandlerId;
 };
@@ -181,7 +185,6 @@ const codecForUIFormFieldBaseDescriptionTemplate = <
     .property("hidden", codecOptional(codecForBoolean()))
     .property("help", codecOptional(codecForString()))
     .property("label", codecForString())
-    .property("name", codecForString())
     .property("tooltip", codecOptional(codecForString()));
 
 const codecForUIFormFieldBaseConfigTemplate = <

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