* Fix invalid select options * Add test for multiselect filling and fix bug with csv reporting * Fix options getting duplicated * Add getQueryBuilderConfig tests
94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
import type { z } from "zod";
|
|
|
|
import type { Field, FormResponse } from "../types/types";
|
|
import { areSelectOptionsInLegacyFormat } from "./selectOptions";
|
|
|
|
/**
|
|
* It takes care of correctly transforming the input to label or id depending on various cases
|
|
* - It allows us to prefill with ID or Label
|
|
* - It allows backward compatibility with legacy routes(with labels for options)
|
|
*/
|
|
function transformSelectValue({
|
|
field,
|
|
idOrLabel,
|
|
}: {
|
|
field: Pick<Field, "options" | "type">;
|
|
idOrLabel: string;
|
|
}) {
|
|
idOrLabel = idOrLabel.trim();
|
|
const options = field.options;
|
|
if (!options) {
|
|
return idOrLabel;
|
|
}
|
|
// Because for legacy saved options, routes must have labels in them instead of ids
|
|
const shouldUseLabelAsValue = areSelectOptionsInLegacyFormat(
|
|
field as typeof field & z.BRAND<"FIELD_WITH_OPTIONS">
|
|
);
|
|
const foundOptionById = options.find((option) => option.id === idOrLabel);
|
|
if (foundOptionById) {
|
|
if (shouldUseLabelAsValue) {
|
|
return foundOptionById.label;
|
|
} else {
|
|
// If shouldUseLabelAsValue is false, then we must use id as value
|
|
// Because shouldUseLabelAsValue is false, id must be set already
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
return foundOptionById.id!;
|
|
}
|
|
} else {
|
|
// No option was found that matches ID
|
|
// So check if the label is provided
|
|
const foundOptionByLabel = options.find((option) => {
|
|
return option.label === idOrLabel;
|
|
});
|
|
if (foundOptionByLabel) {
|
|
if (!shouldUseLabelAsValue) {
|
|
// If shouldUseLabelAsValue is false, then we must use id as value
|
|
// Because shouldUseLabelAsValue is false, id must be set already
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
return foundOptionByLabel.id!;
|
|
}
|
|
}
|
|
}
|
|
return idOrLabel;
|
|
}
|
|
|
|
export function getFieldResponseForJsonLogic({
|
|
field,
|
|
value,
|
|
}: {
|
|
field: Pick<Field, "options" | "type">;
|
|
value: FormResponse[string]["value"] | undefined;
|
|
}) {
|
|
if (!value) {
|
|
return "";
|
|
}
|
|
// type="number" still gives value as a string but we need to store that as number so that number operators can work.
|
|
if (field.type === "number") {
|
|
if (typeof value === "string") {
|
|
return Number(value);
|
|
}
|
|
return value;
|
|
}
|
|
if (field.type === "multiselect") {
|
|
// Could be option id(i.e. a UUIDv4) or option label for ease of prefilling
|
|
let valueOrLabelArray = value instanceof Array ? value : value.toString().split(",");
|
|
|
|
valueOrLabelArray = valueOrLabelArray.map((idOrLabel) => {
|
|
return transformSelectValue({ field, idOrLabel });
|
|
});
|
|
|
|
return valueOrLabelArray;
|
|
}
|
|
|
|
if (field.type === "select") {
|
|
const valueAsStringOrStringArray = typeof value === "number" ? String(value) : value;
|
|
const valueAsString =
|
|
valueAsStringOrStringArray instanceof Array
|
|
? valueAsStringOrStringArray[0]
|
|
: valueAsStringOrStringArray;
|
|
|
|
return transformSelectValue({ field, idOrLabel: valueAsString });
|
|
}
|
|
return value;
|
|
}
|