From c2f6f9d2260787c68a8b46cbe0c0ad80213850d9 Mon Sep 17 00:00:00 2001 From: adonis Date: Wed, 9 Sep 2026 21:03:32 +0330 Subject: [PATCH] fix(register): hide or require referral from settings like other apps Also keep exact trade grams from rial and poll colleague wait every 10s. Co-authored-by: Cursor --- src/components/BasicPacks/BasicInput.vue | 4 +- src/composables/useColleagueOrderWait.ts | 2 +- src/store/settingsStore.ts | 12 +++++ src/utils/serviceFee.ts | 58 +++++++++++++++++++++--- src/views/base/gold/index.vue | 37 +++++++++++++-- src/views/login/components/Register.vue | 38 +++++++++++++--- 6 files changed, 132 insertions(+), 19 deletions(-) diff --git a/src/components/BasicPacks/BasicInput.vue b/src/components/BasicPacks/BasicInput.vue index 8c73d8d..7ed2d24 100644 --- a/src/components/BasicPacks/BasicInput.vue +++ b/src/components/BasicPacks/BasicInput.vue @@ -30,6 +30,8 @@ class="" @change="handlerChange" @input="handlerChange" + @blur="emits('blur', $event)" + @focus="emits('focus', $event)" /> @@ -67,7 +69,7 @@ const addonTextColor = computed(() => props.addonTextColor) const props = withDefaults(defineProps(), { isPassword: false }) -const emits = defineEmits(['update:value', 'onchange']) +const emits = defineEmits(['update:value', 'onchange', 'blur', 'focus']) const localValue = computed({ set(value) { diff --git a/src/composables/useColleagueOrderWait.ts b/src/composables/useColleagueOrderWait.ts index e74fd7a..dd20b74 100644 --- a/src/composables/useColleagueOrderWait.ts +++ b/src/composables/useColleagueOrderWait.ts @@ -9,7 +9,7 @@ import { getToken } from '@/utils' export const colleagueOrderWaiting = ref(false) -const CLIENT_POLL_MS = 5000 +const CLIENT_POLL_MS = 10000 const MAX_WAIT_MS = 15 * 60 * 1000 const STREAM_EVENT = 'colleague-order' diff --git a/src/store/settingsStore.ts b/src/store/settingsStore.ts index 95c2708..30efb2e 100644 --- a/src/store/settingsStore.ts +++ b/src/store/settingsStore.ts @@ -99,6 +99,16 @@ export const useSettingsStore = defineStore('settings', () => { const metalTypeLabel = computed(() => resolveMetalTypeLabel(metalTypeSettingValue.value)) const meltedGoldLabel = computed(() => resolveMeltedGoldLabel(metalTypeSettingValue.value)) const tradeWeightUnit = computed(() => resolveTradeWeightUnit(getSettingByKey('unit'))) + const isReferralFieldVisible = computed(() => { + if (!settings.value?.some((s) => s?.key === 'referral_show')) return true + return isSettingTruthy('referral_show') + }) + + const isReferralRequired = computed(() => { + if (!isReferralFieldVisible.value) return false + const value = String(getSettingByKey('referral_id') ?? '').trim().toLowerCase() + return value === 'required' || value === 'true' || value === '1' || value === 'yes' + }) return { settings, @@ -108,6 +118,8 @@ export const useSettingsStore = defineStore('settings', () => { mergeSettings, getSettingByKey, isSettingTruthy, + isReferralRequired, + isReferralFieldVisible, metalTypeSettingValue, metalTypeLabel, meltedGoldLabel, diff --git a/src/utils/serviceFee.ts b/src/utils/serviceFee.ts index 6b1a7c7..31c3a69 100644 --- a/src/utils/serviceFee.ts +++ b/src/utils/serviceFee.ts @@ -25,9 +25,12 @@ export const TRADE_GRAM_STORAGE_DECIMALS = 10 /** حداکثر اعشار نمایش به کاربر در اپ */ export const TRADE_GRAM_DISPLAY_DECIMALS = 8 -/** اعشار فیلد گرم وقتی از ریال تبدیل می‌شود (فقط نمایش همان فیلد) */ +/** اعشار فیلد گرم وقتی از ریال تبدیل می‌شود (فقط نمایش همان فیلد؛ مقدار دقیق جداست) */ export const TRADE_GRAM_INPUT_DECIMALS = 3 +/** حداکثر اعشاری که کاربر می‌تواند در فیلد گرم تایپ کند */ +export const TRADE_GRAM_TYPING_DECIMALS = 6 + /** زیر این مقدار (گرم)، معادل گرم در فیلد ورودی نشان داده نمی‌شود */ export const TRADE_GRAM_MIN_DISPLAY_GRAMS = 0.0001 @@ -65,7 +68,7 @@ export function formatTradeGramInputValue(grams?: number | null): string | undef return value.toFixed(TRADE_GRAM_INPUT_DECIMALS) } -/** متن اینپوت گرم — فقط نمایش سه‌رقمی؛ منبع حقیقت همان گرم دقیق است */ +/** متن اینپوت گرم وقتی مقدار از ریال آمده — فقط نمایش سه‌رقمی؛ منبع حقیقت همان گرم دقیق است */ export function tradeGramInputDisplay(exactGrams?: number | string | null): string { if (exactGrams === undefined || exactGrams === null || exactGrams === '') return '' const n = Number(exactGrams) @@ -73,6 +76,43 @@ export function tradeGramInputDisplay(exactGrams?: number | string | null): stri return formatTradeGramInputValue(n) ?? '' } +/** متن اینپوت گرم وقتی خود کاربر وزن زده — تا ۶ رقم، بدون پد اجباری */ +export function tradeGramTypedDisplay(exactGrams?: number | string | null): string { + if (exactGrams === undefined || exactGrams === null || exactGrams === '') return '' + const n = Number(exactGrams) + if (!Number.isFinite(n) || n <= 0) return '' + return trimTrailingDecimalZeros(n.toFixed(TRADE_GRAM_TYPING_DECIMALS)) +} + +export function tradeGramFieldText( + exactGrams: number | string | null | undefined, + inputLock: TradeInputLock, + draft: string | null, +): string { + if (draft !== null) return draft + if (inputLock === 'rial') return tradeGramInputDisplay(exactGrams) + return tradeGramTypedDisplay(exactGrams) +} + +/** هنگام تایپ در فیلد گرم: حداکثر شش رقم اعشار؛ نقطهٔ انتهایی برای «۱۲.» نگه داشته می‌شود */ +export function sanitizeTradeGramTypingText(raw: unknown): string { + const text = String(raw ?? '') + if (text === '') return '' + const firstDot = text.indexOf('.') + if (firstDot === -1) return text + const intPart = text.slice(0, firstDot) + const decRaw = text.slice(firstDot + 1).replace(/\./g, '') + if (decRaw === '') return `${intPart}.` + return `${intPart}.${decRaw.slice(0, TRADE_GRAM_TYPING_DECIMALS)}` +} + +/** متن شروع ویرایش وقتی فیلد از روی ریال پر شده (۱.۰۰۰ → ۱) */ +export function tradeGramInputEditText(exactGrams?: number | string | null): string { + const shown = tradeGramInputDisplay(exactGrams) + if (!shown) return '' + return shown.replace(/\.?0+$/, '') +} + /** گرم دقیق از درصد کیف — بدون رند نمایشی اینپوت */ export function exactGoldFromWalletPercent(balance: number, percent: number): number { if (!(Number(percent) > 0) || !(Number(balance) > 0)) return 0 @@ -88,15 +128,21 @@ export function goldFromGramInputDisplay( exactGrams?: number | string | null ): number | undefined { if (raw === '' || raw == null) return undefined - const text = String(raw).trim() - if (text === '') return undefined - const typed = Number(text) + const text = sanitizeTradeGramTypingText(raw).trim() + if (text === '' || text === '.') return undefined + const forNumber = text.endsWith('.') ? text.slice(0, -1) : text + if (forNumber === '') return undefined + const typed = Number(forNumber) if (!Number.isFinite(typed) || typed <= 0) return undefined const exact = Number(exactGrams) if (Number.isFinite(exact) && exact > 0) { const shown = formatTradeGramInputValue(exact) - if (shown != null && text === shown) { + const typedShown = tradeGramTypedDisplay(exact) + if ( + (shown != null && (text === shown || text === shown.replace(/\.?0+$/, ''))) || + text === typedShown + ) { return normalizeOrderGoldAmount(exact) } } diff --git a/src/views/base/gold/index.vue b/src/views/base/gold/index.vue index 175c478..380c05c 100644 --- a/src/views/base/gold/index.vue +++ b/src/views/base/gold/index.vue @@ -84,7 +84,7 @@ + size="large" type="text" inputmode="decimal" @focus="startGramDraft" @blur="commitGramDraft" />
{{ cashValidationMessage }} @@ -289,7 +289,10 @@ import { calcTradeTargetCash, buildTradeConfirmBreakdown, formatTradeGramDisplay, - tradeGramInputDisplay, + tradeGramFieldText, + tradeGramTypedDisplay, + sanitizeTradeGramTypingText, + tradeGramInputEditText, exactGoldFromWalletPercent, goldFromGramInputDisplay, loadServiceFeeFromSettings, @@ -441,13 +444,36 @@ const displayTradeGoldAmount = computed(() => formatTradeGramDisplay(orderGoldAmount.value) ) +const gramInputDraft = ref(null) + +function commitGramDraft() { + gramInputDraft.value = null +} + +function startGramDraft() { + if (gramInputDraft.value !== null) return + gramInputDraft.value = inputLock.value === 'rial' + ? tradeGramInputEditText(form.value.goldValue) + : tradeGramTypedDisplay(form.value.goldValue) +} + const goldValueInput = computed({ get() { - const display = tradeGramInputDisplay(form.value.goldValue) + const display = tradeGramFieldText(form.value.goldValue, inputLock.value, gramInputDraft.value) return display === '' ? undefined : display }, set(raw: string | number | null | undefined) { - const next = goldFromGramInputDisplay(raw, form.value.goldValue) + if (raw === '' || raw == null) { + gramInputDraft.value = '' + form.value.goldValue = undefined + form.value.goldCash = undefined + form.value.percentWallet = 0 + inputLock.value = null + return + } + const text = sanitizeTradeGramTypingText(raw) + gramInputDraft.value = text + const next = goldFromGramInputDisplay(text, form.value.goldValue) form.value.goldValue = next if (next == null) { form.value.goldCash = undefined @@ -645,6 +671,7 @@ onMounted(() => { }) function percentChange(val: number) { + commitGramDraft() if (val !== 0) { if (isBuy.value) { form.value.goldCash = unitCashCalculator.value * val @@ -711,6 +738,7 @@ function calculateCash(val: number) { } function calculateGold(val: number) { + commitGramDraft() inputLock.value = 'rial' const unit = unitPrice.value if (!unit || Number.isNaN(unit)) return @@ -748,6 +776,7 @@ function setIsBuy(val: boolean) { form.value.goldCash = undefined form.value.percentWallet = 0 inputLock.value = null + commitGramDraft() // console.log(bganim.value.classList) // bganim?.value?.classList.add(val?'right':'left') // bganim?.value?.style.transform = `translateX(${val ? '0' : '-100'});` diff --git a/src/views/login/components/Register.vue b/src/views/login/components/Register.vue index f1081d6..2411be2 100644 --- a/src/views/login/components/Register.vue +++ b/src/views/login/components/Register.vue @@ -18,8 +18,18 @@ - - + +