Mohammad Khyata 38565298fc update forms
Co-authored-by: Copilot <copilot@github.com>
2026-05-07 21:02:15 +03:00

77 lines
2.5 KiB
TypeScript

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<typeof relationFieldSchema>
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<typeof customerFormSchema>
export { customerFormSchema, relationFieldSchema }
export type { CustomerFormValues, RelationField }