import { z } from 'zod' /** Which form on the page produced the lead. Surfaces as an amoCRM tag. */ export const leadFormIds = ['request'] as const export type LeadFormId = (typeof leadFormIds)[number] export const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'] as const const optionalText = (max: number) => z .string() .trim() .max(max) .optional() .transform((v) => (v ? v : undefined)) export const leadSchema = z.object({ form: z.enum(leadFormIds), name: z.string().trim().min(1, 'Укажите имя').max(200), phone: z.string().trim().min(5, 'Укажите телефон').max(50), email: z .union([z.email().max(200), z.literal('')]) .optional() .transform((v) => (v ? v : undefined)), /** Hotel or hotel chain the request comes from. */ company: optionalText(200), comment: optionalText(4000), page: optionalText(300), referrer: optionalText(500), // partialRecord, not record: z.record over an enum requires every key. utm: z.partialRecord(z.enum(utmKeys), z.string().max(300)).optional(), /** Honeypot. Bots fill it in; humans never see it. */ website: z.string().max(200).optional(), }) export type LeadPayload = z.infer /** What the client sends — before zod's optional/empty-string normalisation. */ export type LeadInput = z.input export type LeadResponse = | { ok: true; leadId: number; contactId: number } | { ok: false; error: string; fields?: Record }