Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import { jalaaliMonthLength, toGregorian, toJalaali } from 'jalaali-js'
|
|
|
|
import { texts } from '@/texts'
|
|
|
|
export const PERSIAN_MONTHS = texts.common.jalaliMonths
|
|
|
|
export const BIRTH_DATE_MIN_YEAR = 1330
|
|
export const BIRTH_DATE_MAX_YEAR = 1395
|
|
export const BIRTH_DATE_DEFAULT_YEAR = 1370
|
|
|
|
export interface JalaliDateParts {
|
|
day: string
|
|
month: string
|
|
year: string
|
|
[key: string]: string
|
|
}
|
|
|
|
export function birthDateYears(): string[] {
|
|
return Array.from({ length: BIRTH_DATE_MAX_YEAR - BIRTH_DATE_MIN_YEAR + 1 }, (_, index) => String(BIRTH_DATE_MIN_YEAR + index))
|
|
}
|
|
|
|
export function clampJalaliDateParts(value: JalaliDateParts): JalaliDateParts {
|
|
const year = Math.min(BIRTH_DATE_MAX_YEAR, Math.max(BIRTH_DATE_MIN_YEAR, Number(value.year) || BIRTH_DATE_DEFAULT_YEAR))
|
|
const month = Math.min(12, Math.max(1, Number(value.month) || 1))
|
|
const maxDay = jalaaliMonthLength(year, month)
|
|
const day = Math.min(maxDay, Math.max(1, Number(value.day) || 1))
|
|
|
|
return { day: String(day), month: String(month), year: String(year) }
|
|
}
|
|
|
|
export function isoDateToJalaliParts(value: unknown): JalaliDateParts | null {
|
|
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return null
|
|
|
|
const [year, month, day] = value.split('-').map(Number)
|
|
const parsed = new Date(Date.UTC(year, month - 1, day))
|
|
|
|
if (Number.isNaN(parsed.getTime()) || parsed.toISOString().slice(0, 10) !== value) return null
|
|
|
|
const jalali = toJalaali(parsed.getUTCFullYear(), parsed.getUTCMonth() + 1, parsed.getUTCDate())
|
|
|
|
if (jalali.jy < BIRTH_DATE_MIN_YEAR || jalali.jy > BIRTH_DATE_MAX_YEAR) return null
|
|
|
|
return { day: String(jalali.jd), month: String(jalali.jm), year: String(jalali.jy) }
|
|
}
|
|
|
|
export function jalaliPartsToIsoDate(value: JalaliDateParts): string {
|
|
const clamped = clampJalaliDateParts(value)
|
|
const { gy, gm, gd } = toGregorian(Number(clamped.year), Number(clamped.month), Number(clamped.day))
|
|
|
|
return `${gy}-${String(gm).padStart(2, '0')}-${String(gd).padStart(2, '0')}`
|
|
}
|
|
|
|
export function isAllowedBirthDate(value: unknown): value is string {
|
|
return isoDateToJalaliParts(value) !== null
|
|
}
|
|
|
|
export function defaultBirthDateParts(): JalaliDateParts {
|
|
return { day: '1', month: '1', year: String(BIRTH_DATE_DEFAULT_YEAR) }
|
|
}
|