diff options
author | Sebastian <sebasjm@gmail.com> | 2024-05-03 08:43:53 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-05-03 08:44:07 -0300 |
commit | 20353eda268efa962959bead466b59823bfb9b29 (patch) | |
tree | 868d016693f09b40e2c55893d3aed72eca505ecb /packages/aml-backoffice-ui/src/hooks/form.ts | |
parent | fa4c7039f4ebeb6ad3cf19237ad7b138519ac142 (diff) | |
download | wallet-core-20353eda268efa962959bead466b59823bfb9b29.tar.xz |
form hook now takes the shape of the form (do not rely on initial value)
Diffstat (limited to 'packages/aml-backoffice-ui/src/hooks/form.ts')
-rw-r--r-- | packages/aml-backoffice-ui/src/hooks/form.ts | 89 |
1 files changed, 68 insertions, 21 deletions
diff --git a/packages/aml-backoffice-ui/src/hooks/form.ts b/packages/aml-backoffice-ui/src/hooks/form.ts index edeae6085..752444bd2 100644 --- a/packages/aml-backoffice-ui/src/hooks/form.ts +++ b/packages/aml-backoffice-ui/src/hooks/form.ts @@ -15,12 +15,14 @@ */ import { + AbsoluteTime, AmountJson, TalerExchangeApi, TranslatedString, } from "@gnu-taler/taler-util"; import { UIFieldHandler } from "@gnu-taler/web-util/browser"; import { useState } from "preact/hooks"; +import { UIFormFieldConfig, UIHandlerId } from "../context/ui-forms.js"; // export type UIField = { // value: string | undefined; @@ -57,6 +59,8 @@ export type FormErrors<T> = { ? TranslatedString : T[k] extends AmountJson ? TranslatedString + : T[k] extends AbsoluteTime + ? TranslatedString : T[k] extends TalerExchangeApi.AmlState ? TranslatedString : FormErrors<T[k]>; @@ -75,31 +79,22 @@ export type FormStatus<T> = }; function constructFormHandler<T>( + shape: Array<UIHandlerId>, form: RecursivePartial<FormValues<T>>, updateForm: (d: RecursivePartial<FormValues<T>>) => void, errors: FormErrors<T> | undefined, ): FormHandler<T> { - const keys = Object.keys(form) as Array<keyof T>; - const handler = keys.reduce((prev, fieldName) => { - const currentValue: unknown = form[fieldName]; - const currentError: unknown = - errors !== undefined ? errors[fieldName] : undefined; + const handler = shape.reduce((handleForm, fieldId) => { + + const path = fieldId.split(".") + function updater(newValue: unknown) { - updateForm({ ...form, [fieldName]: newValue }); - } - /** - * There is no clear way to know if this object is a custom field - * or a group of fields - */ - if (typeof currentValue === "object") { - // @ts-expect-error FIXME better typing - const group = constructFormHandler(currentValue, updater, currentError); - // @ts-expect-error FIXME better typing - prev[fieldName] = group; - return prev; + updateForm(setValueDeeper(form, path, newValue)); } + const currentValue: unknown = getValueDeeper(form, path) + const currentError: unknown = errors === undefined ? undefined : getValueDeeper(errors, path) const field: UIFieldHandler = { // @ts-expect-error FIXME better typing error: currentError, @@ -108,14 +103,37 @@ function constructFormHandler<T>( onChange: updater, state: {}, }; - // @ts-expect-error FIXME better typing - prev[fieldName] = field; - return prev; + + return setValueDeeper(handleForm, path, field) + + /** + * There is no clear way to know if this object is a custom field + * or a group of fields + */ + // if (typeof currentValue === "object") { + // // @ts-expect-error FIXME better typing + // const group = constructFormHandler(currentValue, updater, currentError); + // // @ts-expect-error FIXME better typing + // prev[fieldName] = group; + // return prev; + // } + + // const field: UIFieldHandler = { + // // @ts-expect-error FIXME better typing + // error: currentError, + // // @ts-expect-error FIXME better typing + // value: currentValue, + // onChange: updater, + // state: {}, + // }; + // handleForm[fieldName] = field; + // return handleForm; }, {} as FormHandler<T>); return handler; } + /** * FIXME: Consider sending this to web-utils * @@ -125,6 +143,7 @@ function constructFormHandler<T>( * @returns */ export function useFormState<T>( + shape: Array<UIHandlerId>, defaultValue: RecursivePartial<FormValues<T>>, check: (f: RecursivePartial<FormValues<T>>) => FormStatus<T>, ): [FormHandler<T>, FormStatus<T>] { @@ -132,7 +151,35 @@ export function useFormState<T>( useState<RecursivePartial<FormValues<T>>>(defaultValue); const status = check(form); - const handler = constructFormHandler(form, updateForm, status.errors); + const handler = constructFormHandler(shape, form, updateForm, status.errors); return [handler, status]; } + + +function getValueDeeper( + object: Record<string, any>, + names: string[], +): UIFieldHandler { + if (names.length === 0) return object as UIFieldHandler; + const [head, ...rest] = names; + if (!head) { + return getValueDeeper(object, rest); + } + if (object === undefined) { + throw Error("handler not found"); + } + return getValueDeeper(object[head], rest); +} + +function setValueDeeper(object: any, names: string[], value: any): any { + if (names.length === 0) return value; + const [head, ...rest] = names; + if (!head) { + return setValueDeeper(object, rest, value); + } + if (object === undefined) { + return { [head]: setValueDeeper({}, rest, value) }; + } + return { ...object, [head]: setValueDeeper(object[head] ?? {}, rest, value) }; +} |