193 lines
7.8 KiB
TypeScript
193 lines
7.8 KiB
TypeScript
const TOKEN_LABELS: Record<string, string> = {
|
|
restaurant: "رستوران",
|
|
hospitality: "رستوران و پذیرایی",
|
|
platform: "پلتفرم",
|
|
starter: "Starter",
|
|
growth: "رشد",
|
|
professional: "حرفهای",
|
|
pro: "حرفهای",
|
|
enterprise: "سازمانی",
|
|
loyalty: "باشگاه مشتریان",
|
|
delivery: "ارسال و پیک",
|
|
booking: "رزرو",
|
|
payment: "پرداخت",
|
|
accounting: "حسابداری",
|
|
website: "وبسایت",
|
|
crm: "مدیریت ارتباط با مشتری",
|
|
inventory: "انبارداری",
|
|
pos: "صندوق فروش",
|
|
monthly: "ماهانه",
|
|
yearly: "سالانه",
|
|
annual: "سالانه",
|
|
trial: "آزمایشی",
|
|
active: "فعال",
|
|
inactive: "غیرفعال",
|
|
draft: "پیشنویس",
|
|
published: "منتشرشده",
|
|
pending: "در انتظار",
|
|
verified: "تأییدشده",
|
|
failed: "ناموفق",
|
|
expired: "منقضیشده",
|
|
trialing: "دوره آزمایشی",
|
|
public: "عمومی",
|
|
private: "خصوصی",
|
|
hidden: "پنهان",
|
|
route: "داخل سامانه",
|
|
external: "پیوند بیرونی",
|
|
disabled: "غیرفعال",
|
|
deny: "غیرفعال",
|
|
allow: "فعال",
|
|
enterprise_quote: "استعلام قیمت",
|
|
irr: "ریال",
|
|
recommended: "پیشنهادشده",
|
|
popular: "محبوب",
|
|
most_popular: "محبوبترین",
|
|
};
|
|
|
|
export const FIELD_LABELS: Record<string, string> = {
|
|
display_name: "نام نمایشی",
|
|
title: "عنوان",
|
|
description: "توضیح کوتاه",
|
|
status: "وضعیت",
|
|
role: "نوع اشتراک",
|
|
pricing_model: "مدل پرداخت",
|
|
amount_minor: "قیمت",
|
|
currency: "واحد پول",
|
|
interval: "دوره پرداخت",
|
|
trial_days: "مدت دوره آزمایشی",
|
|
duration_days: "مدت دوره آزمایشی",
|
|
grace_period_days: "مهلت تمدید",
|
|
product_codes: "محصولات",
|
|
capability_codes: "قابلیتها",
|
|
feature_refs: "امکانات",
|
|
pricing_refs: "روشهای پرداخت",
|
|
discount_refs: "تخفیفها",
|
|
coupon_code: "کد تخفیف",
|
|
tax_class_code: "مالیات",
|
|
trial_eligible: "دوره آزمایشی",
|
|
visibility: "نمایش",
|
|
display_order: "ترتیب نمایش",
|
|
category: "دستهبندی",
|
|
is_verified: "وضعیت تأیید",
|
|
domain_type: "نوع دامنه",
|
|
current_period_end: "تاریخ تمدید",
|
|
trial_ends_at: "پایان دوره آزمایشی",
|
|
created_at: "تاریخ ایجاد",
|
|
updated_at: "آخرین تغییر",
|
|
metadata: "اطلاعات تکمیلی",
|
|
attributes: "ویژگیها",
|
|
parameters: "تنظیمات",
|
|
usage_limits: "سقف استفاده",
|
|
feature_limits: "محدودیت امکانات",
|
|
auto_disable: "غیرفعالسازی خودکار",
|
|
expiration_behavior: "رفتار پس از پایان",
|
|
ssl_ready: "وضعیت SSL",
|
|
dns_instructions: "راهنمای DNS",
|
|
custom_domain_allowed: "دامنه اختصاصی",
|
|
subdomain_only: "فقط زیردامنه",
|
|
reason: "دلیل پیشنهاد",
|
|
};
|
|
|
|
const TECHNICAL_FIELD = /(^id$|_id$|_code$|^code$|^source$|^version_code$|^schema_version$|^rule_trace$|^href$|_route$|launch_strategy)/i;
|
|
|
|
export function isTechnicalField(key: string): boolean {
|
|
return TECHNICAL_FIELD.test(key);
|
|
}
|
|
|
|
export function fieldLabel(key: string): string {
|
|
if (FIELD_LABELS[key]) return FIELD_LABELS[key];
|
|
const translated = key
|
|
.split(/[_\-.]+/)
|
|
.map((token) => TOKEN_LABELS[token.toLowerCase()] || "")
|
|
.filter(Boolean)
|
|
.join(" ");
|
|
return translated || "اطلاعات تکمیلی";
|
|
}
|
|
|
|
export function enumLabel(value: unknown): string {
|
|
if (typeof value === "boolean") return value ? "بله" : "خیر";
|
|
if (value == null || value === "") return "ثبت نشده";
|
|
const raw = String(value).trim();
|
|
return TOKEN_LABELS[raw.toLowerCase()] || humanizeCommercialCode(raw);
|
|
}
|
|
|
|
export function humanizeCommercialCode(code: unknown, explicitName?: string | null): string {
|
|
if (explicitName?.trim() && !looksTechnical(explicitName)) return explicitName.trim();
|
|
if (code == null) return "مورد تجاری";
|
|
const raw = String(code).trim();
|
|
if (!raw) return "مورد تجاری";
|
|
if (TOKEN_LABELS[raw.toLowerCase()]) return TOKEN_LABELS[raw.toLowerCase()];
|
|
if (!looksTechnical(raw)) return raw;
|
|
|
|
const tokens = raw.toLowerCase().split(/[._:/-]+/).filter(Boolean);
|
|
const kind = tokens[0];
|
|
const translated = tokens
|
|
.slice(1)
|
|
.map((token) => TOKEN_LABELS[token])
|
|
.filter(Boolean);
|
|
const subject = translated.join(" ");
|
|
|
|
if (kind === "price" || kind === "plan") {
|
|
const planSubject = translated.filter((token) => token !== "ماهانه" && token !== "سالانه" && token !== "آزمایشی").join(" ");
|
|
return `پلن ${planSubject || "اشتراک"}`.trim();
|
|
}
|
|
if (kind === "bundle") return subject ? `بسته شروع ${subject.replace("Starter", "").trim()}`.trim() : "بسته پیشنهادی";
|
|
if (kind === "product") return subject ? `سیستم ${subject}` : "سیستم کسبوکار";
|
|
if (kind === "capability" || kind === "feature") return subject || "قابلیت کاربردی";
|
|
if (kind === "tax") return subject || "مالیات";
|
|
if (kind === "coupon" || kind === "discount") return subject || "تخفیف";
|
|
return subject || "گزینه تجاری";
|
|
}
|
|
|
|
export function looksTechnical(value: string): boolean {
|
|
return (
|
|
/[a-z0-9]+[._:/][a-z0-9_.:/-]+/i.test(value) ||
|
|
/^[a-z][a-z0-9_]+$/i.test(value) ||
|
|
/\b(payload|json|registry|runtime|frontend|backend|metadata|heuristic|fallback|trace|api)\b/i.test(value)
|
|
);
|
|
}
|
|
|
|
export function formatMoney(amount?: number | null, currency?: string | null): string {
|
|
if (amount == null) return "استعلام قیمت";
|
|
const unit = !currency || /irr|rial/i.test(currency) ? "ریال" : enumLabel(currency);
|
|
return `${new Intl.NumberFormat("fa-IR").format(amount)} ${unit}`;
|
|
}
|
|
|
|
export function formatDate(value?: string | null): string {
|
|
if (!value) return "ثبت نشده";
|
|
const date = new Date(value);
|
|
return Number.isNaN(date.getTime())
|
|
? "ثبت نشده"
|
|
: new Intl.DateTimeFormat("fa-IR", { dateStyle: "medium" }).format(date);
|
|
}
|
|
|
|
export function friendlyMessage(message?: string | null, fallback = "در حال حاضر اطلاعاتی برای نمایش نداریم."): string {
|
|
if (!message || looksTechnical(message) || /\b(4\d\d|5\d\d)\b/.test(message)) return fallback;
|
|
return message.replace(/\[object Object\]/g, "اطلاعات تکمیلی");
|
|
}
|
|
|
|
export function recommendationReason(reason?: string | null): string {
|
|
if (!reason || looksTechnical(reason)) return "بر اساس پاسخهای شما";
|
|
const normalized = reason.toLowerCase();
|
|
if (/branch|شعب/.test(normalized)) return "چون چند شعبه دارید";
|
|
if (/delivery|ارسال/.test(normalized)) return "چون ارسال کالا دارید";
|
|
if (/online|website|وب/.test(normalized)) return "چون فروش آنلاین دارید";
|
|
if (/pos|in.person|حضوری|فروش/.test(normalized)) return "چون فروش حضوری دارید";
|
|
if (/loyal|باشگاه/.test(normalized)) return "چون باشگاه مشتریان برای شما مهم است";
|
|
if (/booking|reservation|رزرو/.test(normalized)) return "چون به مدیریت رزرو نیاز دارید";
|
|
return reason;
|
|
}
|
|
|
|
export function presentValue(value: unknown): string | string[] | Record<string, unknown> {
|
|
if (Array.isArray(value)) {
|
|
return value.map((item) =>
|
|
typeof item === "string" ? humanizeCommercialCode(item) : enumLabel(item)
|
|
);
|
|
}
|
|
if (value && typeof value === "object") return value as Record<string, unknown>;
|
|
if (typeof value === "string") return enumLabel(value);
|
|
if (typeof value === "boolean") return value ? "بله" : "خیر";
|
|
if (typeof value === "number") return new Intl.NumberFormat("fa-IR").format(value);
|
|
return "ثبت نشده";
|
|
}
|