aboutsummaryrefslogtreecommitdiff
path: root/packages/exchange-backoffice-ui/src/handlers/forms.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/exchange-backoffice-ui/src/handlers/forms.ts')
-rw-r--r--packages/exchange-backoffice-ui/src/handlers/forms.ts93
1 files changed, 93 insertions, 0 deletions
diff --git a/packages/exchange-backoffice-ui/src/handlers/forms.ts b/packages/exchange-backoffice-ui/src/handlers/forms.ts
new file mode 100644
index 000000000..b5d1a2b20
--- /dev/null
+++ b/packages/exchange-backoffice-ui/src/handlers/forms.ts
@@ -0,0 +1,93 @@
+import { TranslatedString } from "@gnu-taler/taler-util";
+import { InputText } from "./InputText.js";
+import { InputDate } from "./InputDate.js";
+import { InputInteger } from "./InputInteger.js";
+import { h as create, Fragment, VNode } from "preact";
+import { InputChoiceStacked } from "./InputChoice.js";
+import { InputArray } from "./InputArray.js";
+import { InputSelectMultiple } from "./InputSelectMultiple.js";
+import { InputTextArea } from "./InputTextArea.js";
+import { InputFile } from "./InputFile.js";
+
+export type DoubleColumnForm = DoubleColumnFormSection[];
+
+type DoubleColumnFormSection = {
+ title: TranslatedString;
+ description?: TranslatedString;
+ fields: UIFormField[];
+};
+
+/**
+ * Constrain the type with the ui props
+ */
+type FieldType = {
+ separator: {};
+ array: Parameters<typeof InputArray>[0];
+ file: Parameters<typeof InputFile>[0];
+ selectMultiple: Parameters<typeof InputSelectMultiple>[0];
+ text: Parameters<typeof InputText>[0];
+ textArea: Parameters<typeof InputTextArea>[0];
+ choiceStacked: Parameters<typeof InputChoiceStacked>[0];
+ date: Parameters<typeof InputDate>[0];
+ integer: Parameters<typeof InputInteger>[0];
+};
+
+/**
+ * List all the form fields so typescript can type-check the form instance
+ */
+export type UIFormField =
+ | { type: "separator"; props: FieldType["separator"] }
+ | { type: "array"; props: FieldType["array"] }
+ | { type: "file"; props: FieldType["file"] }
+ | { type: "selectMultiple"; props: FieldType["selectMultiple"] }
+ | { type: "text"; props: FieldType["text"] }
+ | { type: "textArea"; props: FieldType["textArea"] }
+ | { type: "choiceStacked"; props: FieldType["choiceStacked"] }
+ | { type: "integer"; props: FieldType["integer"] }
+ | { type: "date"; props: FieldType["date"] };
+
+type FieldComponentFunction<key extends keyof FieldType> = (
+ props: FieldType[key],
+) => VNode;
+
+type UIFormFieldMap = {
+ [key in keyof FieldType]: FieldComponentFunction<key>;
+};
+
+function Separator(): VNode {
+ return create("div", {});
+}
+
+/**
+ * Maps input type with component implementation
+ */
+const UIFormConfiguration: UIFormFieldMap = {
+ separator: Separator,
+ array: InputArray,
+ text: InputText,
+ file: InputFile,
+ textArea: InputTextArea,
+ date: InputDate,
+ choiceStacked: InputChoiceStacked,
+ integer: InputInteger,
+ selectMultiple: InputSelectMultiple,
+};
+
+export function RenderAllFieldsByUiConfig({
+ fields,
+}: {
+ fields: UIFormField[];
+}): VNode {
+ return create(
+ Fragment,
+ {},
+ fields.map((field, i) => {
+ const Component = UIFormConfiguration[
+ field.type
+ ] as FieldComponentFunction<any>;
+ const c = structuredClone(field.props);
+ c.key = i;
+ return Component(c);
+ }),
+ );
+}