/** * @fileoverview * * This file holds the utilities to build the options to render in the select field and it could be loaded on client side as well. */ import type { z } from "zod"; import type { zodFieldView } from "../zod"; type Field = z.infer; const buildOptionsFromLegacySelectText = ({ legacySelectText }: { legacySelectText: string }) => { return legacySelectText .trim() .split("\n") .map((fieldValue) => ({ label: fieldValue, id: null, })); }; export const getFieldWithOptions = (field: T) => { const legacySelectText = field.selectText; if (field.options) { return { ...field, options: field.options, }; } else if (legacySelectText) { const options = buildOptionsFromLegacySelectText({ legacySelectText }); return { ...field, options, }; } return { ...field, } as typeof field & z.BRAND<"FIELD_WITH_OPTIONS">; }; export function areSelectOptionsInLegacyFormat( field: Pick & z.BRAND<"FIELD_WITH_OPTIONS"> ) { const options = field.options || []; return !!options.find((option) => !option.id); } export function getUIOptionsForSelect(field: Field) { const fieldWithOptions = getFieldWithOptions(field); const options = fieldWithOptions.options || []; const areOptionsInLegacyFormat = areSelectOptionsInLegacyFormat( fieldWithOptions as typeof fieldWithOptions & z.BRAND<"FIELD_WITH_OPTIONS"> ); // Because for legacy saved options, routes must have labels in them instead of ids const shouldUseLabelAsValue = areOptionsInLegacyFormat; return options.map((option) => { // We prefer option.id as that doesn't change when we change the option text/label. // Fallback to option.label for fields saved in DB in old format which didn't have `options` const value = shouldUseLabelAsValue ? option.label : option.id ?? option.label; return { value, title: option.label, }; }); }