207 lines
5.3 KiB
TypeScript
207 lines
5.3 KiB
TypeScript
import * as yup from "yup"
|
|
import type { NationalIdType, DriverCardType } from "../types/driver";
|
|
|
|
// ── Create schema ─────────────────────────────────────────────────────────────
|
|
|
|
export const createDriverSchema = yup.object({
|
|
// Required
|
|
name: yup
|
|
.string()
|
|
.required("الاسم مطلوب")
|
|
.min(2, "الاسم يجب أن يكون حرفين على الأقل"),
|
|
|
|
phone: yup
|
|
.string()
|
|
.required("رقم الجوال مطلوب")
|
|
.matches(
|
|
/^(\+966|966|0)?5[0-9]{8}$/,
|
|
"رقم الجوال غير صالح — يجب أن يكون رقم سعودي صحيح",
|
|
),
|
|
|
|
// Optional
|
|
email: yup
|
|
.string()
|
|
.email("البريد الإلكتروني غير صالح")
|
|
.optional(),
|
|
|
|
address: yup
|
|
.string()
|
|
.min(5, "العنوان يجب أن يكون 5 أحرف على الأقل")
|
|
.optional(),
|
|
|
|
nationality: yup
|
|
.string()
|
|
.min(5, "الجنسية يجب أن تكون 5 أحرف على الأقل")
|
|
.optional(),
|
|
|
|
nationalIdType: yup
|
|
.mixed<NationalIdType>()
|
|
.oneOf(["NationalID", "Iqama", "Passport"], "نوع الهوية غير صالح")
|
|
.optional(),
|
|
|
|
gosiNumber: yup.string().optional(),
|
|
|
|
licenseNumber: yup.string().optional(),
|
|
|
|
licenseType: yup.string().optional(),
|
|
|
|
licenseExpiry: yup
|
|
.string()
|
|
.test(
|
|
"not-in-past",
|
|
"تاريخ انتهاء الرخصة يجب أن يكون اليوم أو في المستقبل",
|
|
(val) => {
|
|
if (!val) return true; // optional
|
|
return new Date(val) >= new Date(new Date().toDateString());
|
|
},
|
|
)
|
|
.optional(),
|
|
|
|
driverCardNumber: yup.string().optional(),
|
|
|
|
driverCardType: yup
|
|
.mixed<DriverCardType>()
|
|
.oneOf(
|
|
["Temporary", "Seasonal", "Annual", "Restricted"],
|
|
"نوع بطاقة السائق غير صالح",
|
|
)
|
|
.optional(),
|
|
|
|
driverCardExpiry: yup
|
|
.string()
|
|
.test(
|
|
"not-in-past",
|
|
"تاريخ انتهاء بطاقة السائق يجب أن يكون اليوم أو في المستقبل",
|
|
(val) => {
|
|
if (!val) return true;
|
|
return new Date(val) >= new Date(new Date().toDateString());
|
|
},
|
|
)
|
|
.optional(),
|
|
|
|
driverType: yup.string().optional(),
|
|
|
|
branchId: yup
|
|
.string()
|
|
.uuid("معرّف الفرع غير صالح")
|
|
.optional(),
|
|
});
|
|
|
|
// ── Update schema (same rules, all optional except they don't change) ─────────
|
|
|
|
export const updateDriverSchema = yup.object({
|
|
name: yup
|
|
.string()
|
|
.min(2, "الاسم يجب أن يكون حرفين على الأقل")
|
|
.optional(),
|
|
|
|
phone: yup
|
|
.string()
|
|
.matches(
|
|
/^(\+966|966|0)?5[0-9]{8}$/,
|
|
"رقم الجوال غير صالح — يجب أن يكون رقم سعودي صحيح",
|
|
)
|
|
.optional(),
|
|
|
|
email: yup
|
|
.string()
|
|
.email("البريد الإلكتروني غير صالح")
|
|
.optional(),
|
|
|
|
address: yup
|
|
.string()
|
|
.min(5, "العنوان يجب أن يكون 5 أحرف على الأقل")
|
|
.optional(),
|
|
|
|
nationality: yup
|
|
.string()
|
|
.min(5, "الجنسية يجب أن تكون 5 أحرف على الأقل")
|
|
.optional(),
|
|
|
|
nationalIdType: yup
|
|
.mixed<NationalIdType>()
|
|
.oneOf(["NationalID", "Iqama", "Passport"], "نوع الهوية غير صالح")
|
|
.optional(),
|
|
|
|
gosiNumber: yup.string().optional(),
|
|
|
|
licenseNumber: yup.string().optional(),
|
|
|
|
licenseType: yup.string().optional(),
|
|
|
|
licenseExpiry: yup
|
|
.string()
|
|
.test(
|
|
"not-in-past",
|
|
"تاريخ انتهاء الرخصة يجب أن يكون اليوم أو في المستقبل",
|
|
(val) => {
|
|
if (!val) return true;
|
|
return new Date(val) >= new Date(new Date().toDateString());
|
|
},
|
|
)
|
|
.optional(),
|
|
|
|
driverCardNumber: yup.string().optional(),
|
|
|
|
driverCardType: yup
|
|
.mixed<DriverCardType>()
|
|
.oneOf(
|
|
["Temporary", "Seasonal", "Annual", "Restricted"],
|
|
"نوع بطاقة السائق غير صالح",
|
|
)
|
|
.optional(),
|
|
|
|
driverCardExpiry: yup
|
|
.string()
|
|
.test(
|
|
"not-in-past",
|
|
"تاريخ انتهاء بطاقة السائق يجب أن يكون اليوم أو في المستقبل",
|
|
(val) => {
|
|
if (!val) return true;
|
|
return new Date(val) >= new Date(new Date().toDateString());
|
|
},
|
|
)
|
|
.optional(),
|
|
|
|
driverType: yup.string().optional(),
|
|
|
|
branchId: yup
|
|
.string()
|
|
.uuid("معرّف الفرع غير صالح")
|
|
.optional(),
|
|
|
|
status: yup
|
|
.mixed<"Active" | "Inactive" | "InTrip" | "Suspended">()
|
|
.oneOf(
|
|
["Active", "Inactive", "InTrip", "Suspended"],
|
|
"حالة السائق غير صالحة",
|
|
)
|
|
.optional(),
|
|
|
|
reason: yup.string().optional(),
|
|
});
|
|
|
|
// ── Infer form error shape ────────────────────────────────────────────────────
|
|
|
|
export type DriverSchemaErrors = Partial<
|
|
Record<
|
|
| "name"
|
|
| "phone"
|
|
| "email"
|
|
| "address"
|
|
| "nationality"
|
|
| "nationalIdType"
|
|
| "gosiNumber"
|
|
| "licenseNumber"
|
|
| "licenseType"
|
|
| "licenseExpiry"
|
|
| "driverCardNumber"
|
|
| "driverCardType"
|
|
| "driverCardExpiry"
|
|
| "driverType"
|
|
| "branchId"
|
|
| "status"
|
|
| "reason",
|
|
string
|
|
>
|
|
>; |