fix(wallet): honor configured quota units for reward transfers (#5808)
* fix(wallet): honor configured quota units for reward transfers * fix(i18n): localize quota preview descriptions * fix(settings): normalize invalid quota input
This commit is contained in:
@@ -24,9 +24,15 @@ import { Dialog } from '@/components/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { formatQuota } from '@/lib/format'
|
||||
|
||||
import { QUOTA_PER_DOLLAR } from '../../constants'
|
||||
import {
|
||||
formatQuota,
|
||||
parseQuotaFromDollars,
|
||||
quotaUnitsToDollars,
|
||||
} from '@/lib/format'
|
||||
import {
|
||||
DEFAULT_CURRENCY_CONFIG,
|
||||
useSystemConfigStore,
|
||||
} from '@/stores/system-config-store'
|
||||
|
||||
interface TransferDialogProps {
|
||||
open: boolean
|
||||
@@ -44,17 +50,34 @@ export function TransferDialog({
|
||||
transferring,
|
||||
}: TransferDialogProps) {
|
||||
const { t } = useTranslation()
|
||||
const [amount, setAmount] = useState(QUOTA_PER_DOLLAR)
|
||||
const currencyConfig = useSystemConfigStore(
|
||||
(state) => state.config.currency
|
||||
)
|
||||
const minimumQuota = Math.ceil(
|
||||
currencyConfig.quotaPerUnit > 0
|
||||
? currencyConfig.quotaPerUnit
|
||||
: DEFAULT_CURRENCY_CONFIG.quotaPerUnit
|
||||
)
|
||||
const minimumAmount = quotaUnitsToDollars(minimumQuota)
|
||||
const maximumAmount = quotaUnitsToDollars(availableQuota)
|
||||
const [amount, setAmount] = useState(minimumAmount)
|
||||
const transferQuota = parseQuotaFromDollars(amount)
|
||||
const canTransfer =
|
||||
Number.isFinite(amount) &&
|
||||
transferQuota >= minimumQuota &&
|
||||
transferQuota <= availableQuota
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setAmount(QUOTA_PER_DOLLAR)
|
||||
setAmount(minimumAmount)
|
||||
}
|
||||
}, [open])
|
||||
}, [minimumAmount, open])
|
||||
|
||||
const handleConfirm = async () => {
|
||||
const success = await onConfirm(amount)
|
||||
if (!canTransfer) return
|
||||
|
||||
const success = await onConfirm(transferQuota)
|
||||
if (success) {
|
||||
onOpenChange(false)
|
||||
}
|
||||
@@ -80,7 +103,10 @@ export function TransferDialog({
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button onClick={handleConfirm} disabled={transferring}>
|
||||
<Button
|
||||
onClick={handleConfirm}
|
||||
disabled={transferring || !canTransfer}
|
||||
>
|
||||
{transferring && <Loader2 className='mr-2 h-4 w-4 animate-spin' />}
|
||||
{t('Transfer')}
|
||||
</Button>
|
||||
@@ -109,13 +135,13 @@ export function TransferDialog({
|
||||
type='number'
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(Number(e.target.value))}
|
||||
min={QUOTA_PER_DOLLAR}
|
||||
max={availableQuota}
|
||||
step={QUOTA_PER_DOLLAR}
|
||||
min={minimumAmount}
|
||||
max={maximumAmount}
|
||||
step={minimumAmount}
|
||||
className='font-mono text-lg'
|
||||
/>
|
||||
<p className='text-muted-foreground text-xs'>
|
||||
{t('Minimum:')} {formatQuota(QUOTA_PER_DOLLAR)}
|
||||
{t('Minimum:')} {formatQuota(minimumQuota)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,11 +55,6 @@ export const PAYMENT_ICON_COLORS = {
|
||||
[PAYMENT_TYPES.WAFFO_PANCAKE]: '#F97316',
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Quota conversion rate: 500,000 units = $1
|
||||
*/
|
||||
export const QUOTA_PER_DOLLAR = 500000
|
||||
|
||||
/**
|
||||
* Default discount rate (no discount)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user