admin/validation/auth.ts
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

45 lines
1.5 KiB
TypeScript

import { z } from 'zod'
import { convertPersianToEnglish } from '@/helpers'
import { isAllowedBirthDate } from '@/lib/birthDate'
import { texts } from '@/texts'
const IRAN_MOBILE_PATTERN = /^(\+?98|0)?9\d{9}$/
const toEnglishDigits = (value: unknown) => (typeof value === 'string' ? convertPersianToEnglish(value).trim() : value)
const v = texts.validation.auth
const person = texts.validation.person
export const SendOtpFormValidation = z.object({
mobile: z.preprocess(toEnglishDigits, z.string().min(1, v.mobileRequired).regex(IRAN_MOBILE_PATTERN, v.mobileInvalid)),
})
export const OTP_LENGTH = 4
export const CheckOtpFormValidation = z.object({
code: z.preprocess(
toEnglishDigits,
z
.string()
.min(OTP_LENGTH, v.otpInvalid)
.max(OTP_LENGTH, v.otpInvalid)
.regex(new RegExp(`^\\d{${OTP_LENGTH}}$`), v.otpDigits)
),
})
export const CompleteProfileFormValidation = z.object({
firstName: z.string().trim().min(1, person.firstNameRequired).max(100, person.firstNameMax),
lastName: z.string().trim().min(1, person.lastNameRequired).max(100, person.lastNameMax),
gender: z
.string()
.min(1, person.genderRequired)
.refine((value): value is 'male' | 'female' => ['male', 'female'].includes(value), {
message: person.genderRequired,
}),
dateOfBirth: z.string().min(1, texts.common.birthDatePlaceholder).refine(isAllowedBirthDate, { message: v.birthDateRange }),
cityId: z.string().min(1, texts.validation.cityRequired),
})
export type CompleteProfileFormValues = z.infer<typeof CompleteProfileFormValidation>