diff options
author | Sebastian <sebasjm@gmail.com> | 2024-03-08 14:09:31 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-03-08 14:09:31 -0300 |
commit | ddd32a690bd13b1eb1aef1356a1d59fd64e254bf (patch) | |
tree | 44126872f6e8195a3617e2002c696c0afa13fb0d /packages/bank-ui/src/hooks/form.ts | |
parent | e0e82cdf07930d766081e42203c5a4e66d43191f (diff) | |
download | wallet-core-ddd32a690bd13b1eb1aef1356a1d59fd64e254bf.tar.xz |
demobank => bank
Diffstat (limited to 'packages/bank-ui/src/hooks/form.ts')
-rw-r--r-- | packages/bank-ui/src/hooks/form.ts | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/packages/bank-ui/src/hooks/form.ts b/packages/bank-ui/src/hooks/form.ts new file mode 100644 index 000000000..26354b108 --- /dev/null +++ b/packages/bank-ui/src/hooks/form.ts @@ -0,0 +1,100 @@ +/* + 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 { AmountJson, TalerBankConversionApi, TranslatedString } from "@gnu-taler/taler-util"; +import { useState } from "preact/hooks"; + +export type UIField = { + value: string | undefined; + onUpdate: (s: string) => void; + error: TranslatedString | undefined; +} + +type FormHandler<T> = { + [k in keyof T]?: + T[k] extends string ? UIField : + T[k] extends AmountJson ? UIField : + FormHandler<T[k]>; +} + +export type FormValues<T> = { + [k in keyof T]: + T[k] extends string ? (string | undefined) : + T[k] extends AmountJson ? (string | undefined) : + FormValues<T[k]>; +} + +export type RecursivePartial<T> = { + [k in keyof T]?: + T[k] extends string ? (string) : + T[k] extends AmountJson ? (AmountJson) : + RecursivePartial<T[k]>; +} + +export type FormErrors<T> = { + [k in keyof T]?: + T[k] extends string ? (TranslatedString) : + T[k] extends AmountJson ? (TranslatedString) : + FormErrors<T[k]>; +} + +export type FormStatus<T> = { + status: "ok", + result: T, + errors: undefined, +} | { + status: "fail", + result: RecursivePartial<T>, + errors: FormErrors<T>, +} + + +function constructFormHandler<T>(form: FormValues<T>, updateForm: (d: 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: any = form[fieldName]; + const currentError: any = errors ? errors[fieldName] : undefined; + function updater(newValue: any) { + updateForm({ ...form, [fieldName]: newValue }) + } + if (typeof currentValue === "object") { + const group = constructFormHandler(currentValue, updater, currentError) + // @ts-expect-error asdasd + prev[fieldName] = group + return prev; + } + const field: UIField = { + error: currentError, + value: currentValue, + onUpdate: updater + } + // @ts-expect-error asdasd + prev[fieldName] = field + return prev + }, {} as FormHandler<T>) + + return handler; +} + +export function useFormState<T>(defaultValue: FormValues<T>, check: (f: FormValues<T>) => FormStatus<T>): [FormHandler<T>, FormStatus<T>] { + const [form, updateForm] = useState<FormValues<T>>(defaultValue) + + const status = check(form) + const handler = constructFormHandler(form, updateForm, status.errors) + + return [handler, status] +}
\ No newline at end of file |