import { z } from 'zod'; import { baseListQuerySchema } from '@/lib/api/route-helpers'; import { DOCUMENT_TYPES, DOCUMENT_STATUSES } from '@/lib/constants'; export const createDocumentSchema = z.object({ interestId: z.string().optional(), clientId: z.string().optional(), documentType: z.enum(DOCUMENT_TYPES), title: z.string().min(1).max(200), notes: z.string().optional(), }); export const updateDocumentSchema = z.object({ title: z.string().min(1).max(200).optional(), notes: z.string().optional(), status: z.enum(DOCUMENT_STATUSES).optional(), }); const wizardSignerSchema = z.object({ signerName: z.string().min(1), signerEmail: z.string().email(), signerRole: z.enum(['client', 'sales', 'approver', 'developer', 'other']), signingOrder: z.number().int().min(1), }); export const createDocumentWizardSchema = z .object({ source: z.enum(['template', 'upload']).default('template'), templateId: z.string().optional(), uploadedFileId: z.string().optional(), documentType: z.enum(DOCUMENT_TYPES), title: z.string().min(1).max(200), notes: z.string().optional(), interestId: z.string().optional(), reservationId: z.string().optional(), clientId: z.string().optional(), companyId: z.string().optional(), yachtId: z.string().optional(), signers: z.array(wizardSignerSchema).optional(), signingMode: z.enum(['sequential', 'parallel']).default('sequential'), pathway: z.enum(['documenso-template', 'inapp', 'upload']).default('documenso-template'), watchers: z.array(z.string()).default([]), reminderCadenceOverride: z.number().int().min(1).max(365).nullable().optional(), remindersDisabled: z.boolean().default(false), autoPlaceFields: z.boolean().default(true), sendImmediately: z.boolean().default(true), }) .refine( (d) => [d.interestId, d.reservationId, d.clientId, d.companyId, d.yachtId].filter(Boolean).length === 1, { message: 'Exactly one subject (interest/reservation/client/company/yacht) is required' }, ) .refine((d) => d.source !== 'template' || Boolean(d.templateId), { path: ['templateId'], message: 'templateId is required when source=template', }) .refine((d) => d.source !== 'upload' || Boolean(d.uploadedFileId), { path: ['uploadedFileId'], message: 'uploadedFileId is required when source=upload', }); export type CreateDocumentWizardInput = z.infer; export const documentsHubTabs = [ 'all', 'eoi_queue', 'awaiting_them', 'awaiting_me', 'completed', 'expired', ] as const; export type DocumentsHubTab = (typeof documentsHubTabs)[number]; export const listDocumentsSchema = baseListQuerySchema.extend({ interestId: z.string().optional(), clientId: z.string().optional(), documentType: z.string().optional(), status: z.string().optional(), /** Hub tab filter — applies tab-specific status / signer-membership constraints. */ tab: z.enum(documentsHubTabs).optional(), /** Restrict to docs being watched by this user id. */ watcherUserId: z.string().optional(), /** When true, only docs intended for signing (default true on hub). */ signatureOnly: z .enum(['true', 'false']) .optional() .transform((v) => (v === undefined ? undefined : v === 'true')), sentSince: z.string().datetime().optional(), sentUntil: z.string().datetime().optional(), }); export const uploadSignedSchema = z.object({ documentId: z.string().min(1), }); export type CreateDocumentInput = z.infer; export type UpdateDocumentInput = z.infer; export type ListDocumentsInput = z.infer;