Files
pn-new-crm/src/lib/validators/interests.ts
Matt 67d7e6e3d5
Some checks failed
Build & Push Docker Images / build-and-push (push) Has been cancelled
Build & Push Docker Images / deploy (push) Has been cancelled
Build & Push Docker Images / lint (push) Has been cancelled
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00

97 lines
4.6 KiB
TypeScript

import { z } from 'zod';
import { baseListQuerySchema } from '@/lib/api/route-helpers';
import { PIPELINE_STAGES, LEAD_CATEGORIES } from '@/lib/constants';
// ─── Create ──────────────────────────────────────────────────────────────────
export const createInterestSchema = z.object({
clientId: z.string().min(1),
berthId: z.string().optional(),
pipelineStage: z.enum(PIPELINE_STAGES).default('open'),
leadCategory: z.enum(LEAD_CATEGORIES).optional(),
source: z.string().optional(),
notes: z.string().optional(),
tagIds: z.array(z.string()).optional().default([]),
reminderEnabled: z.boolean().optional().default(false),
reminderDays: z.number().int().min(1).optional(),
});
// ─── Update ──────────────────────────────────────────────────────────────────
export const updateInterestSchema = createInterestSchema
.omit({ clientId: true, tagIds: true })
.partial();
// ─── Change Stage ─────────────────────────────────────────────────────────────
export const changeStageSchema = z.object({
pipelineStage: z.enum(PIPELINE_STAGES),
reason: z.string().optional(),
});
// ─── List ─────────────────────────────────────────────────────────────────────
export const listInterestsSchema = baseListQuerySchema.extend({
clientId: z.string().optional(),
berthId: z.string().optional(),
pipelineStage: z
.string()
.transform((v) => v.split(',').filter(Boolean))
.optional(),
leadCategory: z.enum(LEAD_CATEGORIES).optional(),
eoiStatus: z.string().optional(),
tagIds: z
.string()
.transform((v) => v.split(',').filter(Boolean))
.optional(),
});
// ─── Waiting List ─────────────────────────────────────────────────────────────
export const waitingListAddSchema = z.object({
clientId: z.string().min(1),
priority: z.enum(['normal', 'high']).default('normal'),
notifyPref: z.enum(['email', 'in_app', 'both']).default('email'),
notes: z.string().optional(),
});
// ─── Generate Recommendations ─────────────────────────────────────────────────
export const generateRecommendationsSchema = z.object({
interestId: z.string().min(1),
});
// ─── Public Interest ──────────────────────────────────────────────────────────
export const publicInterestSchema = z.object({
fullName: z.string().min(1).max(200),
email: z.string().email(),
phone: z.string().optional(),
companyName: z.string().optional(),
yachtName: z.string().optional(),
yachtLengthFt: z.coerce.number().positive().optional(),
yachtWidthFt: z.coerce.number().positive().optional(),
yachtDraftFt: z.coerce.number().positive().optional(),
preferredBerthSize: z.string().optional(),
source: z.literal('website').default('website'),
notes: z.string().max(2000).optional(),
});
// ─── Reorder Waiting List ─────────────────────────────────────────────────────
export const reorderWaitingListSchema = z.object({
entryId: z.string().min(1),
newPosition: z.coerce.number().int().min(1),
});
// ─── Types ────────────────────────────────────────────────────────────────────
export type CreateInterestInput = z.infer<typeof createInterestSchema>;
export type UpdateInterestInput = z.infer<typeof updateInterestSchema>;
export type ChangeStageInput = z.infer<typeof changeStageSchema>;
export type ListInterestsInput = z.infer<typeof listInterestsSchema>;
export type WaitingListAddInput = z.infer<typeof waitingListAddSchema>;
export type PublicInterestInput = z.infer<typeof publicInterestSchema>;
export type ReorderWaitingListInput = z.infer<typeof reorderWaitingListSchema>;