Files
nademitex_admin/src/utils/format.ts
T

101 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const persianDigits = '۰۱۲۳۴۵۶۷۸۹'
const numberFormatter = new Intl.NumberFormat('fa-IR', { useGrouping: true })
export function normalizeDigits(input: string): string {
return input.replace(/[۰-۹]/g, (digit) => String(persianDigits.indexOf(digit)))
}
export function extractNumericString(input: string): string {
return normalizeDigits(input).replace(/[^\d]/g, '')
}
export function parseFormattedNumber(value: string): number {
const numeric = extractNumericString(value)
return numeric ? Number(numeric) : 0
}
export function formatNumber(value: number): string {
if (!Number.isFinite(value)) return '—'
return numberFormatter.format(value)
}
export function formatCurrency(value: number): string {
return `${formatNumber(value)} تومان`
}
export function formatMeterage(value: number): string {
return `${formatNumber(value)} متر`
}
export function toPersianDigits(input: string | number): string {
return String(input).replace(/\d/g, (d) => persianDigits[Number(d)]!)
}
const persianDateFormatter = new Intl.DateTimeFormat('fa-IR-u-ca-persian', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
})
const persianDateTimeFormatter = new Intl.DateTimeFormat('fa-IR-u-ca-persian', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
})
/** Detect already-Jalali date strings like 1403/07/30 or 1403-07-30 */
function isJalaliDateString(value: string): boolean {
const normalized = normalizeDigits(value.trim()).replace(/-/g, '/')
const match = normalized.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})/)
if (!match) return false
const year = Number(match[1])
return year >= 1300 && year <= 1500
}
function toDateValue(date: string | Date): Date {
if (typeof date !== 'string') return date
const trimmed = date.trim()
// فقط تاریخِ بدون ساعت (YYYY-MM-DD) را به‌صورت تقویم محلی بخوان تا شیفت UTC روز را جابه‌جا نکند.
// رشته‌های دارای ساعت (…T10:30:00 یا … 10:30) باید کامل پارس شوند.
const dateOnly = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/)
if (dateOnly && Number(dateOnly[1]) >= 1700) {
return new Date(Number(dateOnly[1]), Number(dateOnly[2]) - 1, Number(dateOnly[3]))
}
const parsed = new Date(trimmed)
if (Number.isNaN(parsed.getTime())) return new Date(NaN)
return parsed
}
export function formatDate(date: string | Date | null | undefined): string {
if (!date) return '—'
if (typeof date === 'string' && isJalaliDateString(date)) {
const normalized = normalizeDigits(date.trim()).replace(/-/g, '/')
const match = normalized.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})/)
if (!match) return toPersianDigits(normalized)
const [, y, m, d] = match
return toPersianDigits(`${y}/${m!.padStart(2, '0')}/${d!.padStart(2, '0')}`)
}
const value = toDateValue(date)
if (Number.isNaN(value.getTime())) return '—'
return persianDateFormatter.format(value)
}
export function formatDateTime(date: string | Date | null | undefined): string {
if (!date) return '—'
if (typeof date === 'string' && isJalaliDateString(date) && !/[T\s]\d/.test(date)) {
return formatDate(date)
}
const value = toDateValue(date)
if (Number.isNaN(value.getTime())) return '—'
return persianDateTimeFormatter.format(value)
}
export function generateOrderNumber(): string {
const year = new Intl.DateTimeFormat('fa-IR-u-ca-persian', { year: 'numeric' }).format(new Date())
const persianYear = year.replace(/[^\d]/g, '') || '1403'
const seq = Math.floor(Math.random() * 9000) + 1000
return `ORD-${persianYear}-${seq}`
}