import * as yup from "yup"; // ── Saudi mobile regex (05xxxxxxxx) ───────────────────────────────────────── const SAUDI_PHONE_RE = /^(05\d{8}|009665\d{8}|\+9665\d{8})$/; // ── Address sub-schemas (mirrors backend orderAddressSchema) ───────────────── // Delivery address — location.coordinates required by the backend (MongoDB GeoJSON) const deliveryAddressSchema = yup.object({ details: yup.object({ city: yup.string().trim().optional(), state: yup.string().trim().optional(), district: yup.string().trim().optional(), street: yup.string().trim().optional(), buildingNo: yup.string().trim().optional(), unitNo: yup.string().trim().optional(), zipCode: yup.string().trim().optional(), }).optional(), location: yup.object({ coordinates: yup .array() .of(yup.number().required()) .length(2, "الإحداثيات يجب أن تكون [خط الطول, خط العرض]") .required("إحداثيات موقع التسليم مطلوبة"), }).required("موقع التسليم مطلوب"), }).optional(); // Pickup address — coordinates optional (user may supply an existing ID instead) const pickupAddressSchema = yup.object({ details: yup.object({ city: yup.string().trim().optional(), state: yup.string().trim().optional(), district: yup.string().trim().optional(), street: yup.string().trim().optional(), buildingNo: yup.string().trim().optional(), unitNo: yup.string().trim().optional(), zipCode: yup.string().trim().optional(), }).optional(), location: yup.object({ coordinates: yup .array() .of(yup.number().required()) .length(2, "الإحداثيات يجب أن تكون [خط الطول, خط العرض]") .optional(), }).optional(), }).optional(); // ── Base shape shared between create & update ──────────────────────────────── // Optional financial / shipment detail fields live here so both schemas // inherit them without repetition. const baseShape = { // ── Optional: shipment details ── type: yup.string().nullable().optional(), quantity: yup .number() .typeError("الكمية يجب أن تكون رقمًا") .min(1, "الكمية يجب أن تكون ١ أو أكثر") .optional(), weight: yup .number() .typeError("الوزن يجب أن يكون رقمًا") .min(0, "الوزن لا يمكن أن يكون سالبًا") .nullable() .optional(), // ── Optional: financial ── subTotal: yup .number() .typeError("الإجمالي الفرعي يجب أن يكون رقمًا") .min(0, "القيمة لا يمكن أن تكون سالبة") .nullable() .optional(), vatRate: yup .number() .typeError("نسبة الضريبة يجب أن تكون رقمًا") .min(0, "النسبة لا يمكن أن تكون سالبة") .max(100, "النسبة لا يمكن أن تتجاوز ١٠٠%") .nullable() .optional(), paymentMethod: yup .mixed<"Cash" | "Card" | "Prepaid">() .oneOf(["Cash", "Card", "Prepaid"], "طريقة الدفع غير صالحة") .nullable() .optional(), }; // ── Create schema ───────────────────────────────────────────────────────────── // The five fields mandated by the task spec are required here. // deliveryAddressId / pickupAddressId intentionally excluded — the backend // generates address records from deliveryAddressData / pickupAddressData. export const createOrderSchema = yup.object({ // ── Required ── tripId: yup .string() .required("الرحلة مطلوبة") .min(1, "الرحلة مطلوبة"), clientId: yup .string() .required("العميل مطلوب") .min(1, "العميل مطلوب"), shipmentNumber: yup .string() .required("رقم الشحنة مطلوب") .min(2, "رقم الشحنة قصير جدًا"), recipientName: yup .string() .required("اسم المستلم مطلوب") .min(2, "اسم المستلم قصير جدًا"), recipientPhone: yup .string() .required("رقم جوال المستلم مطلوب") .matches(SAUDI_PHONE_RE, "أدخل رقم جوال سعودي صحيح (05xxxxxxxx)"), // ── Optional: addresses ── // deliveryAddress: always a new object (backend creates in MongoDB); coordinates required deliveryAddress: deliveryAddressSchema, // pickupAddress: new object OR existing ID — both optional; coordinates optional pickupAddress: pickupAddressSchema, pickupAddressId: yup.string().optional(), // ── Optional inherited ── ...baseShape, }); // ── Update schema ───────────────────────────────────────────────────────────── // All fields are optional on update — the backend applies partial patches. export const updateOrderSchema = yup.object({ tripId: yup.string().nullable().optional(), clientId: yup.string().nullable().optional(), shipmentNumber: yup.string().min(2, "رقم الشحنة قصير جدًا").optional(), recipientName: yup.string().min(2, "اسم المستلم قصير جدًا").optional(), recipientPhone: yup .string() .matches(SAUDI_PHONE_RE, "أدخل رقم جوال سعودي صحيح (05xxxxxxxx)") .optional(), paymentStatus: yup .mixed<"Pending" | "Paid" | "Failed" | "Refunded">() .oneOf(["Pending", "Paid", "Failed", "Refunded"], "حالة الدفع غير صالحة") .nullable() .optional(), // ── Optional: addresses (delivery keeps coordinates required; pickup stays optional) ── deliveryAddress: deliveryAddressSchema, pickupAddress: pickupAddressSchema, pickupAddressId: yup.string().optional(), // ── Optional inherited ── ...baseShape, }); // ── SchemaErrors — typed error bag consumed by OrderFormModal ───────────────── export type CreateOrderSchemaErrors = Partial< Record, string> >; export type UpdateOrderSchemaErrors = Partial< Record, string> >; // Union used inside the modal so one type covers both modes export type OrderSchemaErrors = CreateOrderSchemaErrors & UpdateOrderSchemaErrors;