import { z } from "zod"; import { DYNAMIC_QUESTION_LABEL_MAX_LENGTH, DYNAMIC_QUESTION_PROMPT_MAX_LENGTH, } from "./birth-time-dynamic-question-limits.ts"; const timeSchema = z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/); export const publicChoiceKindSchema = z.enum(["primary", "unknown", "unmatched"]); export type PublicChoiceKind = z.infer; export const timeRangeSchema = z.object({ startTime: timeSchema, endTime: timeSchema, }).strict().readonly(); export type TimeRange = { readonly startTime: string; readonly endTime: string; }; export const publicDynamicChoiceOptionSchema = z.object({ optionId: z.string().trim().min(1), label: z.string().trim().min(1).max(DYNAMIC_QUESTION_LABEL_MAX_LENGTH), kind: publicChoiceKindSchema, }).strict().readonly(); export type PublicDynamicChoiceQuestion = { readonly questionId: string; readonly prompt: string; readonly options: readonly { readonly optionId: string; readonly label: string; readonly kind: PublicChoiceKind; }[]; }; function validateOptionSet( value: { readonly options: readonly { readonly optionId: string; readonly kind: PublicChoiceKind }[] }, context: z.RefinementCtx, ): void { const primaryCount = value.options.filter((option) => option.kind === "primary").length; const unknownCount = value.options.filter((option) => option.kind === "unknown").length; const unmatchedCount = value.options.filter((option) => option.kind === "unmatched").length; if (primaryCount < 2 || primaryCount > 4) { context.addIssue({ code: z.ZodIssueCode.custom, path: ["options"], message: "questions require two to four primary options" }); } if (unknownCount !== 1) { context.addIssue({ code: z.ZodIssueCode.custom, path: ["options"], message: "questions require one unknown option" }); } if (unmatchedCount !== 1) { context.addIssue({ code: z.ZodIssueCode.custom, path: ["options"], message: "questions require one unmatched option" }); } if (new Set(value.options.map((option) => option.optionId)).size !== value.options.length) { context.addIssue({ code: z.ZodIssueCode.custom, path: ["options"], message: "question option ids must be unique" }); } } export const publicDynamicChoiceQuestionSchema = z.object({ questionId: z.string().trim().min(1), prompt: z.string().trim().min(1).max(DYNAMIC_QUESTION_PROMPT_MAX_LENGTH), options: z.array(publicDynamicChoiceOptionSchema).readonly(), }).strict().superRefine(validateOptionSet).readonly(); export { validateOptionSet };