aboutsummaryrefslogtreecommitdiff
path: root/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx')
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx169
1 files changed, 158 insertions, 11 deletions
diff --git a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
index 64bfb90f1..f04d404d0 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
@@ -20,12 +20,14 @@ import {
HttpStatusCode,
TalerExchangeApi,
TalerProtocolTimestamp,
- assertUnreachable,
+ assertUnreachable
} from "@gnu-taler/taler-util";
import {
Button,
+ InternationalizationAPI,
LocalNotificationBanner,
RenderAllFieldsByUiConfig,
+ UIFieldHandler,
UIFormField,
useExchangeApiContext,
useLocalNotificationHandler,
@@ -33,12 +35,40 @@ import {
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { privatePages } from "../Routing.js";
-import { UIFormFieldConfig, useUiFormsContext } from "../context/ui-forms.js";
-import { useFormState } from "../hooks/form.js";
+import {
+ FormMetadata,
+ UIFormFieldConfig,
+ useUiFormsContext,
+} from "../context/ui-forms.js";
+import { preloadedForms } from "../forms/index.js";
+import { FormHandler, useFormState } from "../hooks/form.js";
import { useOfficer } from "../hooks/officer.js";
import { Justification } from "./CaseDetails.js";
import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
+function searchForm(
+ i18n: InternationalizationAPI,
+ forms: FormMetadata[],
+ formId: string,
+): FormMetadata | undefined {
+ {
+ const found = forms.find((v) => v.id === formId);
+ if (found) return found;
+ }
+ {
+ const pf = preloadedForms(i18n);
+ const found = pf.find((v) => v.id === formId);
+ if (found) return found;
+ }
+ return undefined;
+}
+
+type FormType = {
+ when: AbsoluteTime;
+ state: TalerExchangeApi.AmlState;
+ threshold: AmountJson;
+};
+
export function CaseUpdate({
account,
type: formId,
@@ -52,11 +82,10 @@ export function CaseUpdate({
lib: { exchange: api },
} = useExchangeApiContext();
- // const [notification, notify, handleError] = useLocalNotification();
const [notification, withErrorHandler] = useLocalNotificationHandler();
const { config } = useExchangeApiContext();
const { forms } = useUiFormsContext();
- const initial = {
+ const initial: FormType = {
when: AbsoluteTime.now(),
state: TalerExchangeApi.AmlState.pending,
threshold: Amounts.zeroOfCurrency(config.currency),
@@ -65,19 +94,31 @@ export function CaseUpdate({
if (officer.state !== "ready") {
return <HandleAccountNotReady officer={officer} />;
}
- const theForm = forms.find((v) => v.id === formId);
+ const theForm = searchForm(i18n, forms, formId);
if (!theForm) {
return <div>form with id {formId} not found</div>;
}
- const [form, state] = useFormState(initial, (st) => {
+ let defaultValue = initial
+ 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);
+ }
+ });
+ });
+
+
+ const [form, state] = useFormState<FormType>(defaultValue, (st) => {
return {
status: "ok",
result: st as any,
errors: undefined,
};
});
-
+
+ console.log("FORM", form)
const validatedForm = state.status === "fail" ? undefined : state.result;
const submitHandler =
@@ -125,8 +166,73 @@ export function CaseUpdate({
},
);
- function convertUiField(_f: UIFormFieldConfig[]): UIFormField[] {
- return [];
+ 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 (
@@ -155,7 +261,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)}
+ fields={convertUiField(section.fields, form)}
/>
</div>
</div>
@@ -185,7 +291,10 @@ export function CaseUpdate({
}
export function SelectForm({ account }: { account: string }) {
+ const { i18n } = useTranslationContext();
const { forms } = useUiFormsContext();
+ const pf = preloadedForms(i18n);
+
return (
<div>
<pre>New form for account: {account.substring(0, 16)}...</pre>
@@ -200,6 +309,44 @@ export function SelectForm({ account }: { account: string }) {
</a>
);
})}
+ {pf.map((form) => {
+ return (
+ <a
+ key={form.id}
+ href={privatePages.caseUpdate.url({ cid: account, type: form.id })}
+ class="m-4 block rounded-md w-fit border-0 p-3 py-2 text-center text-sm bg-indigo-700 text-white shadow-sm hover:bg-indigo-600"
+ >
+ {form.label}
+ </a>
+ );
+ })}
</div>
);
}
+
+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) };
+}