import { z } from "zod"; import { req, text } from "./common.js"; export const ROLES = ["ADMIN", "EDITOR"]; export const ROLE_LABELS = { ADMIN: "مدیر کل", EDITOR: "ویرایشگر", }; const password = z.string().min(8, "رمز عبور باید حداقل ۸ کاراکتر باشد").max(128); const FA_DIGITS = "۰۱۲۳۴۵۶۷۸۹"; const AR_DIGITS = "٠١٢٣٤٥٦٧٨٩"; /** Normalize Iranian mobile to `09XXXXXXXXX` (Latin digits). */ export function normalizeIrMobile(raw) { let s = raw.trim().replace(/[\s\-()]/g, ""); s = s.replace(/[۰-۹٠-٩]/g, (d) => { const fa = FA_DIGITS.indexOf(d); if (fa >= 0) return String(fa); const ar = AR_DIGITS.indexOf(d); return ar >= 0 ? String(ar) : d; }); if (s.startsWith("+98")) s = `0${s.slice(3)}`; else if (s.startsWith("0098")) s = `0${s.slice(4)}`; else if (s.startsWith("98") && s.length === 12) s = `0${s.slice(2)}`; return s; } export const irMobileSchema = z .string() .trim() .min(1, "شماره موبایل را وارد کنید") .transform(normalizeIrMobile) .pipe(z.string().regex(/^09\d{9}$/, "شماره موبایل معتبر نیست (مثلاً ۰۹۱۲۱۲۳۴۵۶۷)")); export const loginSchema = z.object({ phone: irMobileSchema, password: z.string().min(1, "رمز عبور را وارد کنید").max(128), }); export const changePasswordSchema = z.object({ currentPassword: z.string().min(1, "رمز فعلی را وارد کنید").max(128), newPassword: password, }); export const userCreateSchema = z.object({ phone: irMobileSchema, name: req(80), role: z.enum(ROLES), password, }); export const userUpdateSchema = z.object({ name: req(80), role: z.enum(ROLES), isActive: z.boolean(), /** set only when resetting the password */ password: password.optional(), }); /* ---------------- contact messages ---------------- */ export const MESSAGE_STATUSES = ["NEW", "READ", "ARCHIVED"]; export const MESSAGE_STATUS_LABELS = { NEW: "جدید", READ: "خوانده‌شده", ARCHIVED: "بایگانی", }; export const contactInputSchema = z.object({ name: req(80), org: req(120), phone: z .string() .trim() .min(1, "این فیلد الزامی است") .max(30) .regex(/^[0-9۰-۹+\-\s()]{5,30}$/, "شماره تماس معتبر نیست"), message: text(2000), /** honeypot — real visitors never fill it */ website: z.string().max(200).optional(), }); export const messageUpdateSchema = z.object({ status: z.enum(MESSAGE_STATUSES), }); export const mediaUpdateSchema = z.object({ alt: text(200) }); //# sourceMappingURL=admin.js.map