added some text handling 3
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
/** توضیحات ساده فارسی برای فرمهای ادمین — قابل فهم بدون دانش فنی */
|
||||
|
||||
import { adminHelp } from '@/utils/adminHelpFormat'
|
||||
|
||||
export const bannersPageIntro =
|
||||
'بنرها همان تصاویر اسلایدر بالای صفحهٔ اصلی اپ مشتری هستند. هر کارت = یک اسلاید. بعد از هر تغییر حتماً «ذخیره تغییرات» را بزنید؛ تا آن لحظه در اپ دیده نمیشود.'
|
||||
|
||||
@@ -65,3 +67,37 @@ export const discountExpiryHelp =
|
||||
|
||||
export const priceTriggersPageIntro =
|
||||
'لیست هشدارهای قیمت مشتریان. میتوانید هشدار جدید بسازید، ویرایش کنید، فعال/غیرفعال کنید یا حذف کنید. وقتی قیمت به هدف برسد، به مشتری پیامک یا ایمیل میرود و هشدار خودکار غیرفعال میشود.'
|
||||
|
||||
export const physicalWithdrawPageIntro =
|
||||
'درخواست تحویل فیزیکی طلا یا محصول از کیف مشتری. درخواستهای ثبتشده از اپ مشتری و همینجا توسط ادمین در این لیست دیده میشوند. با ثبت درخواست، مقدار از کیف مشتری کسر میشود. در وضعیت «در انتظار ارسال» با آیکون ویرایش میتوانید مقدار را (حتی اعشاری برای آبشده) تنظیم کنید؛ با «تایید» به «ارسال شده» میرود. برای برداشت ریالی از منوی «برداشت و واریز» استفاده کنید.'
|
||||
|
||||
export const physicalWithdrawCustomerHelp =
|
||||
'مشتریای که میخواهید برایش تحویل فیزیکی ثبت کنید. بعد از انتخاب، لیست محصولات و آدرسهای همان مشتری بارگذاری میشود.'
|
||||
|
||||
export const physicalWithdrawAddressHelp =
|
||||
'آدرسی که محصول به آن ارسال میشود. مشتری آدرسها را در اپ خود ثبت میکند؛ اگر آدرسی ندارد، ابتدا از پنل مشتریان یا از خود مشتری بخواهید آدرس اضافه کند.'
|
||||
|
||||
export const physicalWithdrawProductHelp =
|
||||
'محصولی که مشتری میخواهد فیزیکی تحویل بگیرد. فقط محصولاتی با موجودی بیشتر از صفر نشان داده میشوند.'
|
||||
|
||||
export const physicalWithdrawAmountHelp = adminHelp(
|
||||
'تعداد یا مقدار درخواستی همان واحدی است که در اپ مشتری نمایش داده میشود (مثلاً تعداد سکه یا گرم).',
|
||||
'مقدار درخواستی ≤ موجودی کیف مشتری'
|
||||
)
|
||||
|
||||
export const physicalWithdrawDecreaseHelp =
|
||||
'یک واحد از مقدار این خط کم میکند و همان مقدار به کیف مشتری برمیگردد. فقط وقتی وضعیت «در انتظار ارسال» است.'
|
||||
|
||||
export const physicalWithdrawIncreaseHelp =
|
||||
'یک واحد به مقدار این خط اضافه میکند و از کیف مشتری کسر میشود. فقط وقتی وضعیت «در انتظار ارسال» است و موجودی کافی باشد.'
|
||||
|
||||
export const physicalWithdrawAdjustValueHelp = adminHelp(
|
||||
'مقدار نهایی برداشت را وارد کنید. برای آبشده و محصولات وزنی میتوانید اعشار بزنید (مثلاً ۱.۲۵۰ گرم). برای سکه و محصولات تعدادی فقط عدد صحیح مجاز است.',
|
||||
'مقدار نهایی ≤ موجودی کیف مشتری'
|
||||
)
|
||||
|
||||
export const physicalWithdrawApproveHelp =
|
||||
'درخواست را تایید میکند و وضعیت به «ارسال شده» تغییر میکند؛ یعنی آمادهٔ ارسال یا تحویل است.'
|
||||
|
||||
export const physicalWithdrawStatusHelp =
|
||||
'پیگیری مراحل ارسال: در انتظار ارسال، ارسال شده، لغو شده، یا در انتظار تعیین مجدد قیمت (برای محصولاتی که وزن نهایی مشخص نیست).'
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/** ساختار متن راهنما — توضیح + فرمول اختیاری در کادر جدا */
|
||||
|
||||
export type AdminHelpContent = {
|
||||
description: string
|
||||
formula?: string
|
||||
}
|
||||
|
||||
const FORMULA_MARKER = '\n\n__FORMULA__\n'
|
||||
|
||||
export function adminHelp(description: string, formula?: string): string {
|
||||
const body = description.trim()
|
||||
if (!formula?.trim()) return body
|
||||
return `${body}${FORMULA_MARKER}${formula.trim()}`
|
||||
}
|
||||
|
||||
export function parseAdminHelp(input: string | AdminHelpContent | undefined | null): AdminHelpContent {
|
||||
if (!input) return { description: '' }
|
||||
if (typeof input !== 'string') {
|
||||
return {
|
||||
description: input.description?.trim() ?? '',
|
||||
formula: input.formula?.trim() || undefined,
|
||||
}
|
||||
}
|
||||
|
||||
const marked = input.split(FORMULA_MARKER)
|
||||
if (marked.length === 2) {
|
||||
return {
|
||||
description: marked[0].trim(),
|
||||
formula: marked[1].trim() || undefined,
|
||||
}
|
||||
}
|
||||
|
||||
return { description: input.trim() }
|
||||
}
|
||||
|
||||
export function adminHelpPlainText(content: AdminHelpContent): string {
|
||||
const parts = [content.description].filter(Boolean)
|
||||
if (content.formula) parts.push(content.formula)
|
||||
return parts.join('\n\n')
|
||||
}
|
||||
@@ -1,20 +1,69 @@
|
||||
const PERSIAN_DIGITS = '۰۱۲۳۴۵۶۷۸۹'
|
||||
const ARABIC_DIGITS = '٠١٢٣٤٥٦٧٨٩'
|
||||
|
||||
function toAsciiDigits(value: string): string {
|
||||
return value
|
||||
.replace(/[۰-۹]/g, (d) => String(PERSIAN_DIGITS.indexOf(d)))
|
||||
.replace(/[٠-٩]/g, (d) => String(ARABIC_DIGITS.indexOf(d)))
|
||||
}
|
||||
|
||||
/** پارس مبلغ محدودیت سفارش — ارقام فارسی/عربی و جداکننده هزارگان */
|
||||
export function parseOrderLimitCashValue(value: unknown): number | undefined {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const raw = toAsciiDigits(String(value).trim().replace(/[,\s٬]/g, ''))
|
||||
if (raw === '') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const num = Number(raw)
|
||||
if (!Number.isFinite(num) || num < 0) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return Math.trunc(num)
|
||||
}
|
||||
|
||||
function orderLimitInputsPresent(form: {
|
||||
min_order_cash?: number | string | null
|
||||
max_order_cash?: number | string | null
|
||||
}): boolean {
|
||||
return (
|
||||
(form.min_order_cash != null && form.min_order_cash !== '') ||
|
||||
(form.max_order_cash != null && form.max_order_cash !== '')
|
||||
)
|
||||
}
|
||||
|
||||
export function validateProductOrderLimitForm(form: {
|
||||
order_limit_enabled?: boolean
|
||||
min_order_cash?: number | string | null
|
||||
max_order_cash?: number | string | null
|
||||
}): string | null {
|
||||
if (!form.order_limit_enabled) return null
|
||||
const enabled = !!form.order_limit_enabled || orderLimitInputsPresent(form)
|
||||
if (!enabled) return null
|
||||
|
||||
const min = form.min_order_cash
|
||||
const max = form.max_order_cash
|
||||
const hasMin = min != null && min !== ''
|
||||
const hasMax = max != null && max !== ''
|
||||
const rawMin = form.min_order_cash
|
||||
const rawMax = form.max_order_cash
|
||||
const hasMinInput = rawMin != null && rawMin !== ''
|
||||
const hasMaxInput = rawMax != null && rawMax !== ''
|
||||
const min = parseOrderLimitCashValue(rawMin)
|
||||
const max = parseOrderLimitCashValue(rawMax)
|
||||
|
||||
if (!hasMin && !hasMax) {
|
||||
if (hasMinInput && min == null) {
|
||||
return 'حداقل مبلغ سفارش نامعتبر است'
|
||||
}
|
||||
|
||||
if (hasMaxInput && max == null) {
|
||||
return 'حداکثر مبلغ سفارش نامعتبر است'
|
||||
}
|
||||
|
||||
if (min == null && max == null) {
|
||||
return 'با فعال بودن محدودیت مبلغ سفارش، حداقل یکی از حداقل یا حداکثر مبلغ باید وارد شود'
|
||||
}
|
||||
|
||||
if (hasMin && hasMax && Number(min) > Number(max)) {
|
||||
if (min != null && max != null && min > max) {
|
||||
return 'حداقل مبلغ نمیتواند بیشتر از حداکثر باشد'
|
||||
}
|
||||
|
||||
@@ -22,13 +71,19 @@ export function validateProductOrderLimitForm(form: {
|
||||
}
|
||||
|
||||
export function normalizeProductOrderLimitForm<T extends Record<string, any>>(data: T): T {
|
||||
data.order_limit_enabled = !!data.order_limit_enabled
|
||||
if (!data.order_limit_enabled) {
|
||||
const min = parseOrderLimitCashValue(data.min_order_cash)
|
||||
const max = parseOrderLimitCashValue(data.max_order_cash)
|
||||
const enabled = !!data.order_limit_enabled || min != null || max != null
|
||||
|
||||
data.order_limit_enabled = enabled
|
||||
|
||||
if (!enabled) {
|
||||
data.min_order_cash = undefined
|
||||
data.max_order_cash = undefined
|
||||
} else {
|
||||
data.min_order_cash = data.min_order_cash != null && data.min_order_cash !== '' ? data.min_order_cash : undefined
|
||||
data.max_order_cash = data.max_order_cash != null && data.max_order_cash !== '' ? data.max_order_cash : undefined
|
||||
data.min_order_cash = min
|
||||
data.max_order_cash = max
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user