- settings/company: show success toast on save (2.1) - inspection templates: add explicit Save button (2.6) - parts: label price fields with AED currency (3.1) - service groups: add parts/services picker to packages (3.3) - vehicles: add insurance (has_insurance + insurance type) field (4.2) - appointments: add calendar view with list/calendar toggle (5.1) - job card check-in: require department (5.4) - job card payments: refresh job card/invoice queries so PAID shows (5.6) - vendors: add phone + address fields (6.1) - bill payments: surface real vendor/employee validation errors (6.4) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
44 lines
1.8 KiB
TypeScript
44 lines
1.8 KiB
TypeScript
import { z } from "zod"
|
|
|
|
const optionalStringMaxSchema = (max: number) =>
|
|
z.preprocess(
|
|
(value) => (value === "" || value == null ? undefined : value),
|
|
z.string().max(max, `Must be at most ${max} characters`).optional(),
|
|
)
|
|
|
|
const optionalNumberSchema = z.preprocess(
|
|
(value) => (value === "" || value == null ? undefined : value),
|
|
z.coerce.number().int().optional(),
|
|
)
|
|
|
|
const relationFieldSchema = z
|
|
.object({ value: z.string(), label: z.string() })
|
|
.nullable()
|
|
.optional()
|
|
|
|
const vendorFormSchema = z.object({
|
|
first_name: z.string().trim().min(1, "First name is required").max(50, "First name must be at most 50 characters"),
|
|
last_name: z.string().trim().min(1, "Last name is required").max(50, "Last name must be at most 50 characters"),
|
|
company_name: z.string().trim().min(1, "Company name is required").max(50, "Company name must be at most 50 characters"),
|
|
email: z.string().trim().min(1, "Email is required").email("Enter a valid email address").max(100, "Email must be at most 100 characters"),
|
|
salutation: optionalStringMaxSchema(50),
|
|
phone: optionalStringMaxSchema(20),
|
|
alternate_phone: optionalStringMaxSchema(20),
|
|
opening_balance: optionalNumberSchema,
|
|
credit_limit: optionalNumberSchema,
|
|
website: optionalStringMaxSchema(255),
|
|
// ── Address (optional). Persisted by the backend store endpoint when
|
|
// address_line_1 + country + state are provided. ──
|
|
address_line_1: optionalStringMaxSchema(255),
|
|
address_line_2: optionalStringMaxSchema(255),
|
|
city: optionalStringMaxSchema(100),
|
|
zip_code: optionalStringMaxSchema(20),
|
|
country: relationFieldSchema,
|
|
state: relationFieldSchema,
|
|
})
|
|
|
|
type VendorFormValues = z.infer<typeof vendorFormSchema>
|
|
|
|
export { vendorFormSchema }
|
|
export type { VendorFormValues }
|