import { type ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } const PERSIAN_DIGITS = "۰۱۲۳۴۵۶۷۸۹"; const ARABIC_DIGITS = "٠١٢٣٤٥٦٧٨٩"; /** Normalize user/API money text to a plain Latin numeric string (no thousand separators). */ export function parseMoneyInput(value: string | number | null | undefined): string { if (value === null || value === undefined) return ""; let s = String(value).trim(); if (!s) return ""; s = s .split("") .map((ch) => { const pi = PERSIAN_DIGITS.indexOf(ch); if (pi >= 0) return String(pi); const ai = ARABIC_DIGITS.indexOf(ch); if (ai >= 0) return String(ai); return ch; }) .join(""); s = s.replace(/[,\s٬]/g, "").replace("٫", "."); const negative = s.startsWith("-"); s = s.replace(/-/g, ""); const parts = s.split("."); const intPart = (parts[0] || "").replace(/\D/g, "") || "0"; const decPart = parts.length > 1 ? parts.slice(1).join("").replace(/\D/g, "") : ""; // Preserve empty while user cleared the field (avoid forcing "0" mid-edit). if (!intPart && !decPart && !/[0-9۰-۹٠-٩]/.test(String(value))) return ""; const normalized = decPart ? `${intPart || "0"}.${decPart}` : intPart || "0"; return negative ? `-${normalized}` : normalized; } /** Round/normalize money to integer Rial string (no fractional part). */ export function toRialInteger(value: string | number | null | undefined): string { const raw = parseMoneyInput(value); if (!raw) return ""; const n = Number(raw); if (Number.isNaN(n)) return raw; return String(Math.round(n)); } /** Group every 3 digits for MoneyInput display (LTR Latin digits + comma). Rial: no decimals. */ export function formatMoneyGrouped(value: string | number | null | undefined): string { const raw = toRialInteger(value); if (!raw) return ""; const negative = raw.startsWith("-"); const body = negative ? raw.slice(1) : raw; const grouped = (body || "0").replace(/\B(?=(\d{3})+(?!\d))/g, ","); return negative ? `-${grouped}` : grouped; } /** Display money in fa-IR with thousand separators — Rial has no decimal places. */ export function formatMoney(value: string | number | null | undefined, locale = "fa-IR") { if (value === null || value === undefined || value === "") return "—"; const raw = typeof value === "string" ? parseMoneyInput(value) : String(value); const n = Number(raw); if (Number.isNaN(n)) return String(value); return new Intl.NumberFormat(locale, { maximumFractionDigits: 0, minimumFractionDigits: 0, }).format(Math.round(n)); }