fix(trade): keep exact grams when the input shows rounded display

Percent and cash conversions no longer lose precision by rounding the gram field to three decimals.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-08 14:56:14 +03:30
co-authored by Cursor
parent e9abc9840a
commit 5015fb2838
2 changed files with 69 additions and 15 deletions
+31 -15
View File
@@ -81,10 +81,10 @@
type="price" @onchange="calculateGold" />
</a-form-item>
<a-form-item :rules="[justNumber()]">
<BasicInput v-model:value="form.goldValue" :addon-before="weightUnit" :addon-bg-color="colors.primary"
<BasicInput v-model:value="goldValueInput" :addon-before="weightUnit" :addon-bg-color="colors.primary"
addon-text-color="white"
:place-holder="amountFieldLabel"
size="large" type="text" inputmode="decimal" @onchange="calculateCash" />
size="large" type="text" inputmode="decimal" />
</a-form-item>
<div v-if="cashValidationMessage" class="text-red-700 text-xs font-bold mt-2">
{{ cashValidationMessage }}
@@ -289,7 +289,9 @@ import {
calcTradeTargetCash,
buildTradeConfirmBreakdown,
formatTradeGramDisplay,
formatTradeGramInputValue,
tradeGramInputDisplay,
exactGoldFromWalletPercent,
goldFromGramInputDisplay,
loadServiceFeeFromSettings,
normalizeOrderGoldAmount,
serviceFeePercentage,
@@ -306,7 +308,7 @@ import {
resolveProductTradeIsBuy,
} from '@/utils/productTradeOpen'
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
import { formatProductWalletBalanceText, getCashWalletBalance } from '@/utils/productAssets'
import { useWalletAssets } from '@/composables/useWalletAssets'
import { usesQuantityTrade } from '@/utils/productCategories'
import { useSettingsStore } from '@/store/settingsStore'
@@ -367,11 +369,7 @@ const tradeProductLabel = computed(() => {
const amountFieldLabel = computed(() => `مقدار ${tradeProductLabel.value}`)
const productWalletBalance = computed(() =>
getProductInventoryQuantity(
assetsSummary.value?.inventory_cards ?? [],
props.ProductItem?.id,
walletStore?.walletInfo?.gold
)
Number(walletStore?.walletInfo?.gold ?? 0)
)
const productWalletBalanceText = computed(() =>
@@ -443,6 +441,24 @@ const displayTradeGoldAmount = computed(() =>
formatTradeGramDisplay(orderGoldAmount.value)
)
const goldValueInput = computed({
get() {
const display = tradeGramInputDisplay(form.value.goldValue)
return display === '' ? undefined : display
},
set(raw: string | number | null | undefined) {
const next = goldFromGramInputDisplay(raw, form.value.goldValue)
form.value.goldValue = next
if (next == null) {
form.value.goldCash = undefined
form.value.percentWallet = 0
inputLock.value = null
return
}
calculateCash(next)
},
})
const feeFormHint = computed(() =>
buildTradeConfirmBreakdown({
isBuy: isBuy.value,
@@ -634,9 +650,10 @@ function percentChange(val: number) {
form.value.goldCash = unitCashCalculator.value * val
calculateGold(form.value.goldCash)
} else {
form.value.goldValue = formatTradeGramInputValue(parseFloat(String(unitGoldCalculator.value * val)))
if (form.value.goldValue != null) {
calculateCash(Number(form.value.goldValue))
const grams = exactGoldFromWalletPercent(productWalletBalance.value, val)
form.value.goldValue = grams > 0 ? grams : undefined
if (grams > 0) {
calculateCash(grams)
}
}
} else {
@@ -646,8 +663,6 @@ function percentChange(val: number) {
}
}
const unitGoldCalculator = computed(() => productWalletBalance.value / 100)
const unitCashCalculator = computed(() => {
return cashWalletBalance.value / 100
})
@@ -701,7 +716,8 @@ function calculateGold(val: number) {
if (!unit || Number.isNaN(unit)) return
if (val) {
form.value.goldValue = formatTradeGramInputValue(calcGramFromLockedRial(val, unit, isBuy.value))
const grams = calcGramFromLockedRial(val, unit, isBuy.value)
form.value.goldValue = grams > 0 ? grams : undefined
} else if (val.toString() === '') {
form.value.goldValue = undefined
inputLock.value = null