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.tsx239
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);
+ }
+ }
+ });
+}