import * as yup from "yup"; import type { TripStatus } from "@/types/trip"; const TRIP_STATUSES: TripStatus[] = [ "Scheduled", "InProgress", "Completed", "Cancelled", ]; // NOTE: Unlike driver_validator.ts, there is no actual backend trip validator // file in this handoff. The rules below come from trip_api_reference.html // (marked "// doc") plus a few sensible defaults that are NOT explicitly // stated in the reference (marked "// inferred"). Verify the "inferred" ones // against the real backend validator before relying on them. // ── Create schema ───────────────────────────────────────────────────────────── export const createTripSchema = yup.object({ // Required title: yup .string() .required("عنوان الرحلة مطلوب") .min(3, "عنوان الرحلة يجب أن يكون 3 أحرف على الأقل"), // doc driverId: yup .string() .required("السائق مطلوب") .uuid("معرّف السائق غير صالح"), // doc: UUID, driver must be status=Active (enforced server-side) carId: yup .string() .required("السيارة مطلوبة") .uuid("معرّف السيارة غير صالح"), // doc: UUID, car must be status=Active (enforced server-side) // Optional startTime: yup.string().optional(), // doc: ISO 8601, default now() endTime: yup .string() .optional() .test( "after-start", "وقت الانتهاء يجب أن يكون بعد وقت البدء", function (val) { if (!val) return true; const { startTime } = this.parent; if (!startTime) return true; return new Date(val) > new Date(startTime); // inferred }, ), branchId: yup.string().uuid("معرّف الفرع غير صالح").optional(), // doc status: yup .mixed() .oneOf(TRIP_STATUSES, "حالة الرحلة غير صالحة") .optional(), // doc: default Scheduled collectedCount: yup .number() .typeError("القيمة يجب أن تكون رقم") .integer("القيمة يجب أن تكون رقم صحيح") .min(0, "القيمة لا يمكن أن تكون سالبة") // inferred .optional(), deliveredCount: yup .number() .typeError("القيمة يجب أن تكون رقم") .integer("القيمة يجب أن تكون رقم صحيح") .min(0, "القيمة لا يمكن أن تكون سالبة") // inferred .optional(), returnedCount: yup .number() .typeError("القيمة يجب أن تكون رقم") .integer("القيمة يجب أن تكون رقم صحيح") .min(0, "القيمة لا يمكن أن تكون سالبة") // inferred .optional(), totalCashCollected: yup .number() .typeError("القيمة يجب أن تكون رقم") .min(0, "القيمة لا يمكن أن تكون سالبة") // inferred .optional(), // doc: number | string -> Decimal server-side notes: yup .string() .min(2, "الملاحظات يجب أن تكون حرفين على الأقل") // doc .optional(), endReason: yup .string() .min(2, "سبب الانتهاء يجب أن يكون حرفين على الأقل") // doc .optional(), }); // ── Update schema (same rules, all optional + reason) ───────────────────────── export const updateTripSchema = yup.object({ title: yup .string() .min(3, "عنوان الرحلة يجب أن يكون 3 أحرف على الأقل") .optional(), driverId: yup.string().uuid("معرّف السائق غير صالح").optional(), // doc: must be Active carId: yup.string().uuid("معرّف السيارة غير صالح").optional(), // doc: must be Active status: yup .mixed() .oneOf(TRIP_STATUSES, "حالة الرحلة غير صالحة") .optional(), startTime: yup.string().optional(), endTime: yup .string() .optional() .test( "after-start", "وقت الانتهاء يجب أن يكون بعد وقت البدء", function (val) { if (!val) return true; const { startTime } = this.parent; if (!startTime) return true; return new Date(val) > new Date(startTime); // inferred }, ), branchId: yup.string().uuid("معرّف الفرع غير صالح").optional(), collectedCount: yup .number() .typeError("القيمة يجب أن تكون رقم") .integer("القيمة يجب أن تكون رقم صحيح") .min(0, "القيمة لا يمكن أن تكون سالبة") .optional(), deliveredCount: yup .number() .typeError("القيمة يجب أن تكون رقم") .integer("القيمة يجب أن تكون رقم صحيح") .min(0, "القيمة لا يمكن أن تكون سالبة") .optional(), returnedCount: yup .number() .typeError("القيمة يجب أن تكون رقم") .integer("القيمة يجب أن تكون رقم صحيح") .min(0, "القيمة لا يمكن أن تكون سالبة") .optional(), totalCashCollected: yup .number() .typeError("القيمة يجب أن تكون رقم") .min(0, "القيمة لا يمكن أن تكون سالبة") .optional(), notes: yup .string() .min(2, "الملاحظات يجب أن تكون حرفين على الأقل") .optional(), endReason: yup .string() .min(2, "سبب الانتهاء يجب أن يكون حرفين على الأقل") .optional(), // Update-only: reason for reassigning driver/car (recorded in history) reason: yup.string().optional(), // doc: no explicit min length stated }); // ── Infer form error shape ──────────────────────────────────────────────────── export type TripSchemaErrors = Partial< Record< | "title" | "driverId" | "carId" | "status" | "startTime" | "endTime" | "branchId" | "collectedCount" | "deliveredCount" | "returnedCount" | "totalCashCollected" | "notes" | "endReason" | "reason", string > >;