import { z } from "zod" import { PaymentFor } from "@garage/api" const relationFieldSchema = z .object({ value: z.string(), label: z.string() }) .nullable() const requiredRelationFieldSchema = relationFieldSchema.superRefine((value, ctx) => { if (!value?.value) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "This field is required", }) } }) const optionalStringMax255Schema = z.preprocess( (value) => (value === "" || value == null ? undefined : value), z.string().max(255, "Must be at most 255 characters").optional(), ) const detailsItemSchema = z.object({ bill_id: z.union([z.string(), z.number()]).optional().nullable(), expense_id: z.union([z.string(), z.number()]).optional().nullable(), amount_paid: z.coerce.number().min(0).optional(), }) const paymentMadeFormSchema = z.object({ // ── Relations ── bill: relationFieldSchema, vendor: relationFieldSchema, employee: relationFieldSchema, payment_mode: requiredRelationFieldSchema, // ── Payment info ── amount: z.coerce.number().min(0, "Amount must be 0 or more"), payment_for: z.enum(PaymentFor), payment_number: optionalStringMax255Schema, payment_reference: optionalStringMax255Schema, payment_date: z.string().min(1, "Payment date is required").date("Enter a valid date"), paid_through: optionalStringMax255Schema, notes: z.string().optional(), details: z.array(detailsItemSchema).min(1, "At least one payment detail is required"), }).superRefine((values, ctx) => { const hasBill = Boolean(values.bill?.value) const hasVendor = Boolean(values.vendor?.value) const hasEmployee = Boolean(values.employee?.value) if (values.payment_for === "bill" && !hasBill) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["bill"], message: "Bill is required", }) } if (!hasVendor && !hasEmployee) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["vendor"], message: "Vendor or employee is required", }) ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["employee"], message: "Vendor or employee is required", }) } if (hasVendor && hasEmployee) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["vendor"], message: "Select either a vendor or an employee, not both", }) ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["employee"], message: "Select either a vendor or an employee, not both", }) } }) type PaymentMadeFormValues = z.infer export { paymentMadeFormSchema, relationFieldSchema } export type { PaymentMadeFormValues }