Files
web2.0-frontend/src/views/SignUpPage/FormUtils.tsx
T

163 lines
4.3 KiB
TypeScript

import { Question } from "@components/Widgets/SignupQuestionsWidget/common";
import { SignupForm } from "@models/Signup";
import { EMAIL_REGEX } from "@utils/regexes";
import escapeRegExp from "lodash/escapeRegExp";
const questionToUISchemaProp = (question: Question) => {
let obj: Record<"ui:widget", string>;
if (question.type === "checkbox") {
obj = {
"ui:widget": "checkboxes",
};
} else if (question.type === "radiobutton") {
obj = {
"ui:widget": "radio",
};
}
return {
[question.id]: obj,
};
};
const questionToValidationSchema = (question: Question) => {
let obj: Record<string, unknown>;
if (question.type === "text" || question.type === "name") {
obj = {
type: "string",
title: question.name,
};
} else if (question.type === "info") {
obj = {
type: "null",
title: question.name,
description: question.options,
};
} else if (question.type === "email") {
// Format is just a "FYI" field, so we also have pattern.
obj = {
type: question.required ? ["string"] : ["string", "null"],
title: question.name,
format: "email",
pattern: EMAIL_REGEX.source,
default: null,
};
} else if (question.type === "radiobutton") {
obj = {
type: "string",
title: question.name,
pattern: question.options.map((x) => `^${escapeRegExp(x)}$`).join("|"),
enum: question.options,
};
} else if (question.type === "checkbox") {
obj = {
type: "array",
title: question.name,
uniqueItems: true,
maxItems: question.options.length,
items: {
type: "string",
enum: question.options,
pattern: question.options.map((x) => `^${escapeRegExp(x)}$`).join("|"),
},
};
} else if (question.type === "integer") {
// https://json-schema.org/understanding-json-schema/reference/numeric.html
if (question.options.length === 1) {
obj = {
type: "number",
title: `${question.name} (Max: ${question.options[0]})`,
multipleOf: 1.0,
maximum: Number(question.options[0]),
};
} else if (question.options.length === 2) {
obj = {
type: "number",
title: `${question.name} (${question.options[0]} -- ${question.options[1]})`,
multipleOf: 1.0,
minimum: Number(question.options[0]),
maximum: Number(question.options[1]),
};
} else {
obj = {
type: "number",
title: question.name,
multipleOf: 1.0,
};
}
} else {
throw new Error(`No mapping to schema prop for question type ${question.type}`);
}
return {
[question.id]: obj,
};
};
export const buildFormSchema = (signUpForm: SignupForm) => {
let schemaProps = {};
const { questions } = signUpForm;
const requiredIds = questions.filter((q) => q.required).map((q) => q.id);
const schemaPropsArray = questions.map(questionToValidationSchema);
schemaPropsArray.forEach((schemaProp) => {
schemaProps = {
...schemaProps,
...schemaProp,
};
});
const schema = {
title: signUpForm.id ? signUpForm.title_fi : "Loading...",
type: "object",
required: requiredIds,
properties: schemaProps,
};
return schema;
};
export const buildValidationSchema = (questions: Question[]) => {
let schemaProps = {};
// Force every radiobutton to be required field
questions.forEach((q) => {
if (q.type === "radiobutton") {
// eslint-disable-next-line no-param-reassign
q.required = true;
}
});
const requiredIds = questions.filter((q) => q.required).map((q) => q.id);
const schemaPropsArray = questions.map(questionToValidationSchema);
schemaPropsArray.forEach((schemaProp) => {
schemaProps = {
...schemaProps,
...schemaProp,
};
});
const validationSchema = {
type: "object",
required: requiredIds,
// minProperties: requiredIds.length,
// maxProperties: requiredIds.length,
properties: schemaProps,
};
return validationSchema;
};
export const buildUISchema = (signUpForm: SignupForm) => {
const { questions } = signUpForm;
const uiSchemaPropsArray = questions.map(questionToUISchemaProp);
let uiSchemaProps = {};
uiSchemaPropsArray.forEach((uiSchemaProp) => {
uiSchemaProps = {
...uiSchemaProps,
...uiSchemaProp,
};
});
const uiSchema = {
...uiSchemaProps,
};
return uiSchema;
};