diff options
Diffstat (limited to 'packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx')
-rw-r--r-- | packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx | 239 |
1 files changed, 156 insertions, 83 deletions
diff --git a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx index f04d404d0..bbfa65ca7 100644 --- a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx +++ b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx @@ -20,13 +20,15 @@ import { HttpStatusCode, TalerExchangeApi, TalerProtocolTimestamp, - assertUnreachable + assertUnreachable, } from "@gnu-taler/taler-util"; import { + Addon, Button, InternationalizationAPI, LocalNotificationBanner, RenderAllFieldsByUiConfig, + StringConverter, UIFieldHandler, UIFormField, useExchangeApiContext, @@ -37,14 +39,19 @@ import { Fragment, VNode, h } from "preact"; import { privatePages } from "../Routing.js"; import { FormMetadata, + UIFieldBaseDescription, + UIFormFieldBaseConfig, UIFormFieldConfig, + UIHandlerId, useUiFormsContext, } from "../context/ui-forms.js"; import { preloadedForms } from "../forms/index.js"; -import { FormHandler, useFormState } from "../hooks/form.js"; +import { FormErrors, FormHandler, useFormState } from "../hooks/form.js"; import { useOfficer } from "../hooks/officer.js"; import { Justification } from "./CaseDetails.js"; import { HandleAccountNotReady } from "./HandleAccountNotReady.js"; +import { undefinedIfEmpty } from "./CreateAccount.js"; +import { getConverterById } from "../utils/converter.js"; function searchForm( i18n: InternationalizationAPI, @@ -67,6 +74,7 @@ type FormType = { when: AbsoluteTime; state: TalerExchangeApi.AmlState; threshold: AmountJson; + comment: string; }; export function CaseUpdate({ @@ -89,6 +97,7 @@ export function CaseUpdate({ when: AbsoluteTime.now(), state: TalerExchangeApi.AmlState.pending, threshold: Amounts.zeroOfCurrency(config.currency), + comment: "", }; if (officer.state !== "ready") { @@ -99,27 +108,41 @@ export function CaseUpdate({ return <div>form with id {formId} not found</div>; } - let defaultValue = initial + const shape: Array<UIHandlerId> = []; theForm.config.design.forEach((section) => { section.fields.forEach((field) => { if ("id" in field.properties) { - const path = field.properties.id.split("."); - defaultValue = setValueDeeper(defaultValue, path, undefined); + shape.push(field.properties.id); + // const path = field.properties.id.split("."); + // defaultValue = setValueDeeper(defaultValue, path, undefined); } }); }); - - const [form, state] = useFormState<FormType>(defaultValue, (st) => { + const [form, state] = useFormState<FormType>(shape, initial, (st) => { + const errors = undefinedIfEmpty<FormErrors<FormType>>({ + state: !st.state ? i18n.str`required` : undefined, + threshold: !st.threshold ? i18n.str`required` : undefined, + when: !st.when ? i18n.str`required` : undefined, + comment: !st.comment ? i18n.str`required` : undefined, + }); + if (errors === undefined) { + return { + status: "ok", + result: st as any, + errors: undefined, + }; + } return { - status: "ok", + status: "fail", result: st as any, - errors: undefined, + errors, }; }); - - console.log("FORM", form) - const validatedForm = state.status === "fail" ? undefined : state.result; + + console.log("NOW FORM", form); + + const validatedForm = state.status !== "ok" ? undefined : state.result; const submitHandler = validatedForm === undefined @@ -166,75 +189,6 @@ export function CaseUpdate({ }, ); - function convertUiField( - fieldConfig: UIFormFieldConfig[], - form: FormHandler<unknown>, - ): UIFormField[] { - return fieldConfig.map((config) => { - switch (config.type) { - case "absoluteTime": { - return undefined!; - } - case "amount": { - return { - type: "amount", - properties: { - ...(config.properties as any), - handler: getValueDeeper(form, config.properties.id.split(".")), - }, - } as UIFormField; - } - case "array": { - return undefined!; - } - case "caption": { - return undefined!; - } - case "choiceHorizontal": { - return { - type: "choiceHorizontal", - properties: { - handler: getValueDeeper(form, config.properties.id.split(".")), - choices: config.properties.choices, - }, - } as UIFormField; - } - case "choiceStacked": - case "file": - case "group": - case "integer": - case "selectMultiple": - case "selectOne": { - return undefined!; - } - case "text": { - return { - type: "text", - properties: { - ...(config.properties as any), - handler: getValueDeeper(form, config.properties.id.split(".")), - }, - } as UIFormField; - } - case "textArea": { - return { - type: "text", - properties: { - ...(config.properties as any), - handler: getValueDeeper(form, config.properties.id.split(".")), - }, - } as UIFormField; - } - case "toggle": { - return undefined!; - } - default: { - assertUnreachable(config); - } - } - }); - } - return ( <Fragment> <LocalNotificationBanner notification={notification} /> @@ -261,7 +215,7 @@ export function CaseUpdate({ <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"> <RenderAllFieldsByUiConfig key={i} - fields={convertUiField(section.fields, form)} + fields={convertUiField(i18n, section.fields, form)} /> </div> </div> @@ -281,7 +235,8 @@ export function CaseUpdate({ <Button type="submit" handler={submitHandler} - class="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={!submitHandler} + class="disabled:opacity-50 disabled:cursor-default 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>Confirm</i18n.Translate> </Button> @@ -350,3 +305,121 @@ 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), + handler: getValueDeeper(form, p.id.split(".")), + }; +} + +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}`, + }; +} + +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 "absoluteTime": { + return undefined!; + } + case "amount": { + return { + type: "amount", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + }, + } as UIFormField; + } + case "array": { + return undefined!; + } + case "choiceHorizontal": { + return { + type: "choiceHorizontal", + properties: { + ...converBaseFieldsProps(i18n_, config.properties), + ...converInputFieldsProps(form, config.properties), + choices: config.properties.choices, + }, + } as UIFormField; + } + case "choiceStacked": + case "file": + case "integer": + case "selectMultiple": + case "selectOne": { + return undefined!; + } + 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 undefined!; + } + default: { + assertUnreachable(config); + } + } + }); +} |