diff options
Diffstat (limited to 'packages/aml-backoffice-ui/src/hooks/form.ts')
-rw-r--r-- | packages/aml-backoffice-ui/src/hooks/form.ts | 249 |
1 files changed, 217 insertions, 32 deletions
diff --git a/packages/aml-backoffice-ui/src/hooks/form.ts b/packages/aml-backoffice-ui/src/hooks/form.ts index 752444bd2..033d1d950 100644 --- a/packages/aml-backoffice-ui/src/hooks/form.ts +++ b/packages/aml-backoffice-ui/src/hooks/form.ts @@ -19,10 +19,11 @@ import { AmountJson, TalerExchangeApi, TranslatedString, + assertUnreachable, } from "@gnu-taler/taler-util"; -import { UIFieldHandler } from "@gnu-taler/web-util/browser"; +import { Addon, InternationalizationAPI, UIFieldBaseDescription, UIFieldHandler, UIFormField, UIFormFieldBaseConfig, UIFormFieldConfig, UIHandlerId } from "@gnu-taler/web-util/browser"; import { useState } from "preact/hooks"; -import { UIFormFieldConfig, UIHandlerId } from "../context/ui-forms.js"; +import { getConverterById } from "../utils/converter.js"; // export type UIField = { // value: string | undefined; @@ -93,41 +94,17 @@ function constructFormHandler<T>( updateForm(setValueDeeper(form, path, newValue)); } - const currentValue: unknown = getValueDeeper(form, path) - const currentError: unknown = errors === undefined ? undefined : getValueDeeper(errors, path) + const currentValue = getValueDeeper<string>(form as any, path, undefined) + const currentError = getValueDeeper<TranslatedString>(errors as any, path, undefined) const field: UIFieldHandler = { - // @ts-expect-error FIXME better typing error: currentError, - // @ts-expect-error FIXME better typing value: currentValue, onChange: updater, - state: {}, + state: {}, //FIXME: add the state of the field (hidden, ) }; 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; @@ -156,22 +133,40 @@ export function useFormState<T>( return [handler, status]; } +interface Tree<T> extends Record<string, Tree<T> | T> {} -function getValueDeeper( +function getValueDeeper<T>( + object: Tree<T> | undefined, + names: string[], + notFoundValue?: T, +): T | undefined { + if (names.length === 0) return object as T; + const [head, ...rest] = names; + if (!head) { + return getValueDeeper(object, rest, notFoundValue); + } + if (object === undefined) { + return notFoundValue + } + return getValueDeeper(object[head] as Tree<T>, rest, notFoundValue); +} + +function getValueDeeper2( 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); + return getValueDeeper2(object, rest); } if (object === undefined) { throw Error("handler not found"); } - return getValueDeeper(object[head], rest); + return getValueDeeper2(object[head], rest); } + function setValueDeeper(object: any, names: string[], value: any): any { if (names.length === 0) return value; const [head, ...rest] = names; @@ -183,3 +178,193 @@ function setValueDeeper(object: any, names: string[], value: any): any { } return { ...object, [head]: setValueDeeper(object[head] ?? {}, rest, value) }; } + +function getAddonById(_id: string | undefined): Addon { + return undefined!; +} + + +function converInputFieldsProps( + form: FormHandler<unknown>, + p: UIFormFieldBaseConfig, +) { + return { + converter: getConverterById(p.converterId, p), + handler: getValueDeeper2(form, p.id.split(".")), + name: p.name, + required: p.required, + disabled: p.disabled, + help: p.help, + placeholder: p.placeholder, + tooltip: p.tooltip, + label: p.label as TranslatedString, + }; +} + +function converBaseFieldsProps( + i18n_: InternationalizationAPI, + p: UIFieldBaseDescription, +) { + return { + 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}`, + }; +} + +export function convertUiField( + i18n_: InternationalizationAPI, + fieldConfig: UIFormFieldConfig[], + form: FormHandler<unknown>, +): UIFormField[] { + return fieldConfig.map((config) => { + // NON input fields + switch (config.type) { + case "caption": { + const resp: UIFormField = { + type: config.type, + properties: converBaseFieldsProps(i18n_, config.properties), + }; + return resp; + } + case "group": { + const resp: UIFormField = { + type: config.type, + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + fields: convertUiField(i18n_, config.properties.fields, form), + }, + }; + return resp; + } + } + // Input Fields + switch (config.type) { + case "array": { + return { + type: "array", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + labelField: config.properties.labelFieldId, + fields: convertUiField(i18n_, config.properties.fields, form), + }, + } as UIFormField; + } + case "absoluteTime": { + return { + type: "absoluteTime", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + case "amount": { + return { + type: "amount", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + case "choiceHorizontal": { + return { + type: "choiceHorizontal", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + choices: config.properties.choices, + }, + } as UIFormField; + } + case "choiceStacked": { + return { + type: "choiceStacked", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + choices: config.properties.choices, + + }, + }as UIFormField; + } + case "file":{ + console.log("ASDASD", config.properties.accept) + return { + type: "file", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + accept: config.properties.accept, + maxBites: config.properties.maxBytes, + }, + } as UIFormField; + } + case "integer":{ + return { + type: "integer", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + case "selectMultiple":{ + return { + type: "selectMultiple", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + choices: config.properties.choices, + }, + } as UIFormField; + } + case "selectOne": { + return { + type: "selectOne", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + choices: config.properties.choices, + }, + } as UIFormField; + } + case "text": { + return { + type: "text", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + case "textArea": { + return { + type: "text", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + case "toggle": { + return { + type: "toggle", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + default: { + assertUnreachable(config); + } + } + }); +} |