import { z } from "zod" /** * Reusable schema for relation/lookup fields stored as `{ value, label }` objects. * Use `.nullable()` when the field is optional but explicitly clearable. */ const relationFieldSchema = z .object({ value: z.string(), label: z.string() }) .nullable() type RelationField = z.infer const optionalTrimmedString = (max: number) => z.preprocess( (value) => { if (typeof value !== "string") { return value } const trimmed = value.trim() return trimmed === "" ? undefined : trimmed }, z.string().max(max).optional(), ) const optionalInteger = z.preprocess( (value) => { if (value === "" || value == null) { return undefined } return Number(value) }, z.number().int().optional(), ) const customerFormSchema = z.object({ // ── Relations (stored as objects, mapped to IDs on submit) ── customer_type: relationFieldSchema.refine((val) => !!val?.value, "Customer type is required"), referral_source: relationFieldSchema, payment_terms: relationFieldSchema, country: relationFieldSchema, state: relationFieldSchema, // ── Basic info ── salutation: z.string().trim().min(1, "Salutation is required").max(50, "Salutation cannot exceed 50 characters"), first_name: z.string().trim().min(1, "First name is required").max(50, "First name cannot exceed 50 characters"), last_name: z.string().trim().min(1, "Last name is required").max(50, "Last name cannot exceed 50 characters"), company_name: optionalTrimmedString(50), // ── Contact ── email: z .string() .trim() .min(1, "Email is required") .email("Enter a valid email address") .max(100, "Email cannot exceed 100 characters"), phone: optionalTrimmedString(20), alternate_phone: optionalTrimmedString(20), opening_balance: optionalInteger, credit_limit: optionalInteger, website: optionalTrimmedString(255).refine( (value) => !value || z.string().url().safeParse(value).success, "Enter a valid website URL", ), // ── Address ── address_line_1: optionalTrimmedString(255), address_line_2: optionalTrimmedString(255), city: optionalTrimmedString(100), zip_code: optionalTrimmedString(20), }) type CustomerFormValues = z.infer export { customerFormSchema, relationFieldSchema } export type { CustomerFormValues, RelationField }