commit 09369587931379bfb982defa93551ff022b83cc9
parent 65d955e954fd3eccc7a05f1bbc9c48e5d9212932
Author: Florian Dold <florian@dold.me>
Date: Mon, 21 Jul 2025 13:32:08 +0200
forms: tweaks for GLS forms
Diffstat:
2 files changed, 108 insertions(+), 97 deletions(-)
diff --git a/packages/web-util/src/forms/forms-types.ts b/packages/web-util/src/forms/forms-types.ts
@@ -300,22 +300,22 @@ export type UIFieldElementDescription = ComputableFieldConfig & {
};
export type UIFormFieldBaseConfig = UIFieldElementDescription & {
- /* example to be shown inside the field */
+ /** Example to be shown inside the field */
placeholder?: string;
- /* conversion id to convert the string into the value type
- the id should be known to the ui impl
+ /**
+ * Conversion id to convert the string into the value type.
+ * The id should be known to the ui implementation.
*/
converterId?: string;
- /*
- return an error message if the value is not valid.
- should returns un undefined if there is no error.
- this function is called before conversion
+ /**
+ * Return an error message if the value is not valid,
+ * undefined otherwise.
*/
validator?: (text: string, form: any) => TranslatedString | undefined;
- /* property id of the form */
+ /** Property id of the form */
id: UIHandlerId;
};
diff --git a/packages/web-util/src/forms/gana/gls_merchant_onboarding.ts b/packages/web-util/src/forms/gana/gls_merchant_onboarding.ts
@@ -1,4 +1,4 @@
-import { TalerFormAttributes } from "@gnu-taler/taler-util";
+import { TalerFormAttributes, TranslatedString } from "@gnu-taler/taler-util";
import { intervalToDuration, isFuture, isValid, parse } from "date-fns";
import {
DoubleColumnFormDesign,
@@ -21,6 +21,76 @@ export const form_gls_merchant_onboarding = (
version: 1,
});
+function validateDateOfBirth(
+ i18n: InternationalizationAPI,
+ text: string,
+ _form: any,
+): TranslatedString | undefined {
+ // Date is stored as ISO timestamp
+ const time = parse(text, "yyyy-MM-dd", new Date());
+ if (!isValid(time)) {
+ return i18n.str`invalid format`;
+ }
+ if (isFuture(time)) {
+ return i18n.str`it can't be in the future`;
+ }
+ const { years } = intervalToDuration({
+ start: time,
+ end: new Date(),
+ });
+ if (years && years > 120) {
+ return i18n.str`it can't be greater than 120 years`;
+ }
+ return undefined;
+}
+
+function validateFoundingDate(
+ i18n: InternationalizationAPI,
+ text: string,
+ _form: any,
+): TranslatedString | undefined {
+ // Date is stored as ISO timestamp
+ const time = parse(text, "yyyy-MM-dd", new Date());
+ if (!isValid(time)) {
+ return i18n.str`invalid format`;
+ }
+ if (isFuture(time)) {
+ return i18n.str`it can't be in the future`;
+ }
+ const { years } = intervalToDuration({
+ start: time,
+ end: new Date(),
+ });
+ if (years && years > 120) {
+ return i18n.str`it can't be greater than 120 years`;
+ }
+ return undefined;
+}
+
+function validateEmail(
+ i18n: InternationalizationAPI,
+ text: string,
+ _form: any,
+): TranslatedString | undefined {
+ const re = /^\S+@\S+\.\S+$/;
+ if (re.test(text)) {
+ return undefined;
+ }
+ return i18n.str`Invalid e-mail address`;
+}
+
+function validatePhone(
+ i18n: InternationalizationAPI,
+ text: string,
+ _form: any,
+): TranslatedString | undefined {
+ const re = /^[+]?([0-9]+[. ]*)+$/;
+ if (re.test(text)) {
+ return undefined;
+ }
+ return i18n.str`Invalid phone number`;
+}
+
export function gls_merchant_onboarding(
i18n: InternationalizationAPI,
context?: any,
@@ -30,8 +100,8 @@ export function gls_merchant_onboarding(
title: "Merchant Onboarding Information",
sections: [
{
- title: i18n.str`Personal Information`,
- description: i18n.str`Personal information of the acting person`,
+ title: i18n.str`Personal Details`,
+ description: i18n.str`Personal details of the authorised representative.`,
fields: [
{
id: TalerFormAttributes.PERSON_FIRST_NAMES,
@@ -50,27 +120,10 @@ export function gls_merchant_onboarding(
id: TalerFormAttributes.DATE_OF_BIRTH,
label: i18n.str`Date of birth`,
type: "isoDateText",
- placeholder: "dd/MM/yyyy",
- pattern: "dd/MM/yyyy",
+ placeholder: "dd.MM.yyyy",
+ pattern: "dd.MM.yyyy",
required: true,
- validator(text, form) {
- //FIXME: why returning in this format even if pattern is in another?
- const time = parse(text, "yyyy-MM-dd", new Date());
- if (!isValid(time)) {
- return i18n.str`invalid format`;
- }
- if (isFuture(time)) {
- return i18n.str`it can't be in the future`;
- }
- const { years } = intervalToDuration({
- start: time,
- end: new Date(),
- });
- if (years && years > 120) {
- return i18n.str`it can't be greater than 120 years`;
- }
- return undefined;
- },
+ validator: (text, form) => validateDateOfBirth(i18n, text, form),
},
{
id: TalerFormAttributes.NATIONALITY,
@@ -84,50 +137,14 @@ export function gls_merchant_onboarding(
label: i18n.str`Phone number`,
type: "text",
required: true,
+ validator: (text, form) => validatePhone(i18n, text, form),
},
{
id: TalerFormAttributes.CONTACT_EMAIL,
label: i18n.str`E-Mail`,
type: "text",
required: true,
- },
- ],
- },
- {
- title: i18n.str`Terms of Service`,
- fields: [
- {
- type: "external-link",
- id: TalerFormAttributes.DOWNLOADED_TERMS_OF_SERVICE,
- required: true,
- url: "https://google.com",
- label: i18n.str`Download the term of service`,
- media: "text/plain",
- },
- {
- type: "caption",
- label:
- "You need to download the terms of service before you can accept them.",
- hide(value, root) {
- console.log(
- `hide caption: ${root["DOWNLOADED_TERMS_OF_SERVICE"] === true}`,
- );
- return root["DOWNLOADED_TERMS_OF_SERVICE"] === true;
- },
- },
- {
- type: "toggle",
- id: TalerFormAttributes.ACCEPTED_TERMS_OF_SERVICE,
- required: true,
- label: i18n.str`Do you accept the terms of service?`,
- validator(v) {
- return !v
- ? i18n.str`Can't continue without accepting term of service.`
- : undefined;
- },
- hide(value, root) {
- return !root["DOWNLOADED_TERMS_OF_SERVICE"];
- },
+ validator: (text, form) => validateEmail(i18n, text, form),
},
],
},
@@ -172,27 +189,10 @@ export function gls_merchant_onboarding(
id: TalerFormAttributes.FOUNDING_DATE,
label: i18n.str`Founding date`,
type: "isoDateText",
- placeholder: "dd/MM/yyyy",
- pattern: "dd/MM/yyyy",
+ placeholder: "dd.MM.yyyy",
+ pattern: "dd.MM.yyyy",
required: true,
- validator(text, form) {
- //FIXME: why returning in this format even if pattern is in another?
- const time = parse(text, "yyyy-MM-dd", new Date());
- if (!isValid(time)) {
- return i18n.str`invalid format`;
- }
- if (isFuture(time)) {
- return i18n.str`it can't be in the future`;
- }
- const { years } = intervalToDuration({
- start: time,
- end: new Date(),
- });
- if (years && years > 120) {
- return i18n.str`it can't be greater than 120 years`;
- }
- return undefined;
- },
+ validator: (text, form) => validateFoundingDate(i18n, text, form),
},
{
id: TalerFormAttributes.BUSINESS_IS_NON_PROFIT,
@@ -217,12 +217,6 @@ export function gls_merchant_onboarding(
type: "drilldown",
choices: drilldownGlsIndustries,
},
- // {
- // id: TalerFormAttributes.BUSINESS_INDUSTRY_OTHER,
- // label: i18n.str`Industry (free-form entry for other)`,
- // type: "text",
- // required: true,
- // },
],
},
{
@@ -328,9 +322,11 @@ export function gls_merchant_onboarding(
id: TalerFormAttributes.DATE_OF_BIRTH,
label: i18n.str`Date of birth`,
type: "isoDateText",
- placeholder: "dd/MM/yyyy",
- pattern: "dd/MM/yyyy",
+ placeholder: "dd.MM.yyyy",
+ pattern: "dd.MM.yyyy",
required: true,
+ validator: (text, form) =>
+ validateDateOfBirth(i18n, text, form),
},
{
id: TalerFormAttributes.NATIONALITY,
@@ -363,6 +359,21 @@ export function gls_merchant_onboarding(
},
],
},
+ {
+ title: i18n.str`New Customer Identification`,
+ fields: [
+ {
+ type: "caption",
+ label: "Please complete the customer registration and identification for the authorized representative and other persons listed in this form.",
+ },
+ {
+ type: "external-link",
+ url: "https://kontoeroeffnung.gls.de/kundenanlage/gks-v",
+ id: "none",
+ label: "GLS Customer Registration",
+ }
+ ],
+ },
],
};
}