fix withdraw and desposit ui

This commit is contained in:
2026-06-15 15:48:10 +03:30
parent f7b86a5fa1
commit 57a8fb9854
11 changed files with 438 additions and 100 deletions
+97 -4
View File
@@ -5,11 +5,104 @@ export function getWallets(wallet?: Wallet | Wallet[]): Wallet[] {
return Array.isArray(wallet) ? wallet : [wallet]
}
export function getCashBalance(wallet?: Wallet | Wallet[]): number {
return getWallets(wallet)[0]?.cash ?? 0
/** کیف اصلی مشتری — بدون fund و بدون product */
export function getMainWallet(wallet?: Wallet | Wallet[]): Wallet | undefined {
const wallets = getWallets(wallet)
return wallets.find((w) => w.fund_id == null && w.product_id == null)
}
export function getGoldBalance(wallet?: Wallet | Wallet[]): string {
const sum = getWallets(wallet).reduce((total, item) => total + (item.gold ?? 0), 0)
/** پارس setting `main_wallet_products` — id با کاما یا JSON */
export function parseMainWalletProductIds(raw?: string | null): number[] {
const value = (raw ?? '').trim()
if (!value) return []
try {
const decoded = JSON.parse(value)
if (Array.isArray(decoded)) {
return [...new Set(decoded.map((id) => Number(id)).filter((id) => id > 0))]
}
} catch {
// کاما‌جدا
}
return [
...new Set(
value
.split(',')
.map((part) => Number(part.trim()))
.filter((id) => id > 0)
)
]
}
let cachedMainWalletProductIds: number[] | null = null
export function setCachedMainWalletProductIds(ids: number[]): void {
cachedMainWalletProductIds = ids
}
/** بارگذاری یک‌باره از API تنظیمات */
export async function initMainWalletProductIds(): Promise<number[]> {
if (cachedMainWalletProductIds !== null) {
return cachedMainWalletProductIds
}
const { initWalletSettingsFromApi } = await import('@/utils/config')
await initWalletSettingsFromApi()
return cachedMainWalletProductIds ?? []
}
export function getMainWalletProductIds(): number[] {
return cachedMainWalletProductIds ?? []
}
/**
* موجودی ریالی کیف اصلی.
* با main_wallet_products ممکن است کیف legacy محصول (مثلاً id=13) cash=0 داشته باشد — فقط کیف اصلی معتبر است.
*/
export function getCashBalance(
wallet?: Wallet | Wallet[],
options?: { walletCash?: number | null }
): number {
if (options?.walletCash != null) {
return Number(options.walletCash)
}
return getMainWallet(wallet)?.cash ?? 0
}
/**
* جمع طلای قابل‌نمایش — هم‌راستا با WalletBalanceService سرور.
* کیف legacy محصولات main_wallet_products در جمع نمی‌آید.
*/
export function getGoldBalance(
wallet?: Wallet | Wallet[],
options?: { walletGold?: number | null; mainWalletProductIds?: number[] }
): string {
if (options?.walletGold != null) {
return Number(options.walletGold).toFixed(3)
}
const mainWalletProductIds = options?.mainWalletProductIds ?? getMainWalletProductIds()
const sum = getWallets(wallet).reduce((total, line) => {
const gold = Number(line.gold ?? 0)
if (gold <= 0) return total
if (line.fund_id != null) {
return total + gold
}
if (line.product_id == null) {
return total + gold
}
const productId = Number(line.product_id)
if (mainWalletProductIds.length > 0 && mainWalletProductIds.includes(productId)) {
return total
}
return total + gold
}, 0)
return sum.toFixed(3)
}
+2
View File
@@ -26,6 +26,8 @@ export interface Customer {
city: string
province: string
wallet: Wallet
wallet_cash?: number
wallet_gold?: number
n_code: string | number
last_seen_at:string
profit_amount: number
+6
View File
@@ -5,6 +5,8 @@ export interface Wallet {
id: number
gold: number
cash: number
fund_id?: number | null
product_id?: number | null
customer: User
}
@@ -32,11 +34,15 @@ export interface Withdraw {
transaction?: WithdrawTransaction[]
}
export type WalletChargeDirection = 'charge' | 'discharge'
export interface Charge {
value?: number
note?: string
customer_id?: number
talabBedehi?: boolean
direction?: WalletChargeDirection
amountAbs?: number | string
}
export interface WithdrawStatus {
+3 -3
View File
@@ -67,13 +67,13 @@
is-line
title="کیف پول طلا"
class="mt-2"
:value="selectedCustomer?.wallet[0]?.gold ?? '_'"
:value="getGoldBalance(selectedCustomer?.wallet) || '_'"
/>
<BasicInfoItem
is-line
title="کیف پول ریالی"
class="mt-1"
:value="selectedCustomer?.wallet[0]?.cash ?? '_'"
:value="getCashBalance(selectedCustomer?.wallet) || '_'"
/>
</div>
<div class="flex flex-col gap-2 bg-blue-50 p-2 rounded-lg">
@@ -142,6 +142,7 @@ import { usePrice } from '@core/utils/usePrice'
import { getLastPrice } from '@/api/price'
import type { last } from '@/model/price'
import { createOrder } from '@/api/order'
import { getCashBalance, getGoldBalance } from '@/components/mobile/utils/wallet'
//loading
const loading = ref<boolean>(false)
@@ -217,7 +218,6 @@ async function getPrices() {
async function changeUser(val: Customer) {
selectedCustomer.value = cloneDeep(val)
console.log(selectedCustomer.value.wallet[0])
}
function stopGetPrice() {
+1 -1
View File
@@ -337,7 +337,7 @@ const SETTING_GROUPS: Array<{
id: 'support',
title: 'پشتیبانی اپ کاربر',
icon: 'vuesax-linear:headphone',
match: (k) => k.startsWith('support_messenger')
match: (k) => k.startsWith('support_messenger') || k === 'deposit_sms_support_number'
},
{
id: 'bots',
@@ -88,6 +88,7 @@ const KEY_TYPE_FALLBACK: Record<string, SettingFieldType> = {
support_messenger_id: 'text',
support_messenger_text: 'longtext',
support_messenger: 'select',
deposit_sms_support_number: 'number',
zaarbox_price_key: 'select'
}
@@ -0,0 +1,221 @@
<template>
<a-form
:model="form"
ref="formRef"
autocomplete="off"
class="wallet-charge-form"
:class="formClass"
>
<a-form-item label="نوع عملیات" name="direction">
<a-radio-group
v-model:value="form.direction"
button-style="solid"
class="wallet-charge-form__direction w-full"
>
<a-radio-button value="charge" class="wallet-charge-form__radio wallet-charge-form__radio--charge">
<span class="wallet-charge-form__radio-icon">+</span>
شارژ
</a-radio-button>
<a-radio-button value="discharge" class="wallet-charge-form__radio wallet-charge-form__radio--discharge">
<span class="wallet-charge-form__radio-icon">−</span>
دشارژ
</a-radio-button>
</a-radio-group>
</a-form-item>
<div class="wallet-charge-form__preview" :class="previewClass">
<span class="wallet-charge-form__preview-sign">{{ previewSign }}</span>
<span class="wallet-charge-form__preview-text">{{ previewText }}</span>
</div>
<a-form-item name="talabBedehi">
<a-checkbox v-model:checked="form.talabBedehi">طلب/بدهی</a-checkbox>
</a-form-item>
<a-form-item :label="amountLabel" name="amountAbs" :rules="amountRules">
<BasicInput
v-model:value="form.amountAbs"
:addon-before="unit"
:type="variant === 'money' ? 'price' : 'number'"
:place-holder="amountPlaceholder"
/>
<div v-if="variant === 'money' && Number(form.amountAbs) > 10" class="wallet-charge-form__hint">
معادل {{ usePrice(Number(form.amountAbs) / 10, true, 'تومان') }}
</div>
</a-form-item>
<a-form-item :label="noteLabel" name="note" :rules="inputRules()">
<BasicInput v-model:value="form.note" :place-holder="notePlaceholder" />
</a-form-item>
</a-form>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import type { FormInstance } from 'ant-design-vue'
import type { Charge } from '@/model/wallet'
import { inputRules } from '@/utils/inputRules'
import { usePrice } from '@core/utils/usePrice'
const props = defineProps<{
variant: 'money' | 'gold'
modelValue: Charge
}>()
const emit = defineEmits<{
'update:modelValue': [value: Charge]
}>()
const form = ref<Charge>({ ...props.modelValue })
watch(
() => props.modelValue,
(value) => {
form.value = { ...value }
},
{ deep: true }
)
watch(
form,
(value) => {
emit('update:modelValue', { ...value })
},
{ deep: true }
)
const formRef = ref<FormInstance>()
const unit = computed(() => (props.variant === 'money' ? 'ریال' : 'گرم'))
const isDischarge = computed(() => form.value.direction === 'discharge')
const formClass = computed(() =>
isDischarge.value ? 'wallet-charge-form--discharge' : 'wallet-charge-form--charge'
)
const previewClass = computed(() =>
isDischarge.value
? 'wallet-charge-form__preview--discharge'
: 'wallet-charge-form__preview--charge'
)
const previewSign = computed(() => (isDischarge.value ? '−' : '+'))
const previewText = computed(() => {
const action = isDischarge.value ? 'کسر از' : 'افزایش'
const wallet = props.variant === 'money' ? 'موجودی ریالی' : 'موجودی طلایی'
return `${action} ${wallet} کاربر`
})
const amountLabel = computed(() =>
isDischarge.value ? `مقدار دشارژ (${unit.value})` : `مقدار شارژ (${unit.value})`
)
const noteLabel = computed(() => (isDischarge.value ? 'علت دشارژ' : 'علت شارژ'))
const amountPlaceholder = computed(() =>
props.variant === 'money' ? 'مثلاً ۱۰۰٬۰۰۰' : 'مثلاً ۰.۵'
)
const notePlaceholder = computed(() =>
isDischarge.value ? 'دلیل کسر موجودی' : 'دلیل افزایش موجودی'
)
const amountRules = [
...inputRules('مقدار'),
{
validator: (_rule: unknown, value: string | number | undefined) => {
const num = Math.abs(Number(value) || 0)
if (!num) {
return Promise.reject('مقدار باید بیشتر از صفر باشد')
}
return Promise.resolve()
}
}
]
defineExpose({
validateFields: () => formRef.value?.validateFields()
})
</script>
<style scoped>
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper) {
width: 50%;
text-align: center;
height: 2.75rem;
line-height: 2.65rem;
font-weight: 700;
}
.wallet-charge-form__radio-icon {
display: inline-block;
margin-left: 0.35rem;
font-size: 1.1rem;
font-weight: 800;
}
.wallet-charge-form__preview {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1rem;
padding: 0.85rem 1rem;
border-radius: 0.75rem;
border: 1px solid transparent;
font-size: 0.9rem;
font-weight: 600;
}
.wallet-charge-form__preview-sign {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 9999px;
font-size: 1.15rem;
font-weight: 800;
flex-shrink: 0;
}
.wallet-charge-form__preview--charge {
background: rgba(34, 197, 94, 0.12);
border-color: rgba(34, 197, 94, 0.35);
color: #86efac;
}
.wallet-charge-form__preview--charge .wallet-charge-form__preview-sign {
background: rgba(34, 197, 94, 0.2);
color: #4ade80;
}
.wallet-charge-form__preview--discharge {
background: rgba(239, 68, 68, 0.12);
border-color: rgba(239, 68, 68, 0.35);
color: #fca5a5;
}
.wallet-charge-form__preview--discharge .wallet-charge-form__preview-sign {
background: rgba(239, 68, 68, 0.2);
color: #f87171;
}
.wallet-charge-form__hint {
margin-top: 0.35rem;
font-size: 0.75rem;
opacity: 0.75;
}
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge) {
background: #15803d !important;
border-color: #15803d !important;
color: #fff !important;
}
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge) {
background: #b91c1c !important;
border-color: #b91c1c !important;
color: #fff !important;
}
</style>
@@ -2,6 +2,7 @@ import type { BaseTableColumn } from '@core/type/baseTable'
import {toJalali, toJalaliNoTime, toTime} from '@core/utils/useDataTime'
import CustomTag from '@/components/CustomTag.vue'
import { usePrice } from '@core/utils/usePrice'
import { getCashBalance, getGoldBalance } from '@/components/mobile/utils/wallet'
/*import BudgetSelect from '@/components/BudgetSelect.vue'
import { useStaticApiListsStore } from '@/store/staticApisStore'
import type { FilterSelect } from '@/model/filterSelect'
@@ -75,7 +76,7 @@ export const cols: BaseTableColumn[] = [
key: 'wallet.cash',
type: 'Number',
customRender(data) {
return usePrice(data.record?.wallet[0]?.cash ?? 0, true, '')
return usePrice(getCashBalance(data.record?.wallet, { walletCash: data.record?.wallet_cash }), true, '')
}
},
{
@@ -85,9 +86,7 @@ export const cols: BaseTableColumn[] = [
type: 'Number',
filterable: false,
customRender(data) {
let sum = 0
data.record.wallet.forEach((x) => (sum += x.gold))
return sum.toFixed(3)
return getGoldBalance(data.record?.wallet, { walletGold: data.record?.wallet_gold })
}
},
{
+38 -82
View File
@@ -218,103 +218,59 @@
<BasicActionSheet
v-if="isMobile"
v-model:visible="showMoneyWalletCharge"
title="شارژ کیف پول ریالی"
:title="moneyChargeTitle"
modal-width="24rem"
:loading="loading"
:show-button="true"
:show-cancel="true"
:show-ok="true"
ok-text="ثبت"
:ok-text="moneyChargeOkText"
cancel-text="انصراف"
@ok="chargeMoneyWallet"
@close="showMoneyWalletCharge = false"
>
<a-form :model="formCharge" ref="formChargeRef" autocomplete="off" class="space-y-1">
<a-form-item name="talabBedehi">
<a-checkbox v-model:checked="formCharge.talabBedehi">طلب/بدهی</a-checkbox>
</a-form-item>
<a-form-item label="مقدار شارژ " name="value" :rules="inputRules()">
<BasicInput addon-before="ریال" v-model:value="formCharge.value" type="price" />
<div v-show="formCharge.value > 10">
معادل {{ usePrice(formCharge.value / 10, true, 'تومان') }}
</div>
</a-form-item>
<a-form-item label="علت شارژ " name="note" :rules="inputRules()">
<BasicInput v-model:value="formCharge.note" />
</a-form-item>
</a-form>
<WalletChargeForm ref="moneyChargeFormRef" v-model="formCharge" variant="money" />
</BasicActionSheet>
<BasicModal
v-else
v-model:visible="showMoneyWalletCharge"
width="20rem"
title="شارژ کیف پول ریالی"
width="22rem"
:title="moneyChargeTitle"
:ok-text="moneyChargeOkText"
@ok="chargeMoneyWallet"
:loading="loading"
@close="showMoneyWalletCharge = false"
>
<a-form :model="formCharge" ref="formChargeRef" autocomplete="off">
<a-form-item name="talabBedehi">
<a-checkbox v-model:checked="formCharge.talabBedehi">طلب/بدهی</a-checkbox>
</a-form-item>
<a-form-item label="مقدار شارژ " name="value" :rules="inputRules()">
<BasicInput addon-before="ریال" v-model:value="formCharge.value" type="price" />
<div v-show="formCharge.value > 10">
معادل {{ usePrice(formCharge.value / 10, true, 'تومان') }}
</div>
</a-form-item>
<a-form-item label="علت شارژ " name="note" :rules="inputRules()">
<BasicInput v-model:value="formCharge.note" />
</a-form-item>
</a-form>
<WalletChargeForm ref="moneyChargeFormRef" v-model="formCharge" variant="money" />
</BasicModal>
<BasicActionSheet
v-if="isMobile"
v-model:visible="showGoldWalletCharge"
title="شارژ کیف پول طلایی"
:title="goldChargeTitle"
modal-width="24rem"
:loading="loading"
:show-button="true"
:show-cancel="true"
:show-ok="true"
ok-text="ثبت"
:ok-text="goldChargeOkText"
cancel-text="انصراف"
@ok="chargeGoldWallet"
@close="showGoldWalletCharge = false"
>
<a-form :model="formCharge" ref="formChargeRef" autocomplete="off" class="space-y-1">
<a-form-item name="talabBedehi">
<a-checkbox v-model:checked="formCharge.talabBedehi">طلب/بدهی</a-checkbox>
</a-form-item>
<a-form-item label="مقدار شارژ " name="value" :rules="inputRules()">
<BasicInput addon-before="گرم" v-model:value="formCharge.value" type="number" />
</a-form-item>
<a-form-item label="علت شارژ " name="note" :rules="inputRules()">
<BasicInput v-model:value="formCharge.note" />
</a-form-item>
</a-form>
<WalletChargeForm ref="goldChargeFormRef" v-model="formCharge" variant="gold" />
</BasicActionSheet>
<BasicModal
v-else
v-model:visible="showGoldWalletCharge"
width="20rem"
title="شارژ کیف پول طلایی"
width="22rem"
:title="goldChargeTitle"
:ok-text="goldChargeOkText"
@ok="chargeGoldWallet"
:loading="loading"
@close="showGoldWalletCharge = false"
>
<a-form :model="formCharge" ref="formChargeRef" autocomplete="off">
<a-form-item name="talabBedehi">
<a-checkbox v-model:checked="formCharge.talabBedehi">طلب/بدهی</a-checkbox>
</a-form-item>
<a-form-item label="مقدار شارژ " name="value" :rules="inputRules()">
<BasicInput addon-before="گرم" v-model:value="formCharge.value" type="number" />
</a-form-item>
<a-form-item label="علت شارژ " name="note" :rules="inputRules()">
<BasicInput v-model:value="formCharge.note" />
</a-form-item>
</a-form>
<WalletChargeForm ref="goldChargeFormRef" v-model="formCharge" variant="gold" />
</BasicModal>
<BasicInfoModal
v-model:visible="userInfoOrderVisible"
@@ -333,7 +289,7 @@
// import BasicInfoModal from '@/components/BasicInfoModal'
import { inputLenRules, inputRules } from '@/utils/inputRules'
import { useStaticApiListsStore } from '@/store/staticApisStore'
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import tbl from './components/table.vue'
import type { FormInstance } from 'ant-design-vue'
import BasicInfoModal from '@/components/BasicInfoModal/index.vue'
@@ -359,6 +315,14 @@ import ReferralsTable from '@/pages/menuPages/customers/base/components/referral
import type { Order } from '@/model/order'
import Icon from '@core/components/BaseIcon/src/Icon.vue'
import { isMobile } from '@core/utils/is'
import WalletChargeForm from './components/WalletChargeForm.vue'
import {
buildChargePayload,
createEmptyChargeForm,
walletChargeOkText,
walletChargeSuccessMessage,
walletChargeTitle
} from './utils/walletChargeForm'
//tabs
const activeKey = ref('اطلاعات جامع')
@@ -418,9 +382,15 @@ const userInfoOrderVisible = ref<boolean>(false)
//form
const form = ref<Partial<Customer>>({})
const formCharge = ref<Charge>({})
const formRef = ref<FormInstance>()
const formChargeRef = ref<FormInstance>()
const formCharge = ref<Charge>({})
const moneyChargeFormRef = ref<InstanceType<typeof WalletChargeForm>>()
const goldChargeFormRef = ref<InstanceType<typeof WalletChargeForm>>()
const moneyChargeTitle = computed(() => walletChargeTitle('money', formCharge.value.direction))
const goldChargeTitle = computed(() => walletChargeTitle('gold', formCharge.value.direction))
const moneyChargeOkText = computed(() => walletChargeOkText(formCharge.value.direction))
const goldChargeOkText = computed(() => walletChargeOkText(formCharge.value.direction))
//info
let infoParams = reactive<Info>({})
@@ -540,21 +510,7 @@ async function add() {
}
function resetFormCharge(customerId: number) {
formCharge.value = {
customer_id: customerId,
value: undefined,
note: undefined,
talabBedehi: false
}
}
function buildChargePayload(): Charge {
return {
value: formCharge.value.value,
note: formCharge.value.note,
customer_id: formCharge.value.customer_id,
talabBedehi: formCharge.value.talabBedehi === true
}
formCharge.value = createEmptyChargeForm(customerId)
}
async function walletMoneyCharge(val: Customer) {
@@ -568,11 +524,11 @@ async function walletGoldCharge(val: Customer) {
}
async function chargeMoneyWallet() {
formChargeRef.value?.validateFields().then(async () => {
moneyChargeFormRef.value?.validateFields()?.then(async () => {
try {
loading.value = true
await chargeWallet(buildChargePayload(), 'money')
message.success('افزایش اعتبار با موفقیت انجام شد')
await chargeWallet(buildChargePayload(formCharge.value), 'money')
message.success(walletChargeSuccessMessage(formCharge.value.direction))
showMoneyWalletCharge.value = false
} catch (e) {
console.log(e)
@@ -583,11 +539,11 @@ async function chargeMoneyWallet() {
}
async function chargeGoldWallet() {
formChargeRef.value?.validateFields().then(async () => {
goldChargeFormRef.value?.validateFields()?.then(async () => {
try {
loading.value = true
await chargeWallet(buildChargePayload(), 'gold')
message.success('افزایش اعتبار با موفقیت انجام شد')
await chargeWallet(buildChargePayload(formCharge.value), 'gold')
message.success(walletChargeSuccessMessage(formCharge.value.direction))
showGoldWalletCharge.value = false
} catch (e) {
console.log(e)
@@ -0,0 +1,40 @@
import type { Charge, WalletChargeDirection } from '@/model/wallet'
export function createEmptyChargeForm(customerId: number): Charge {
return {
customer_id: customerId,
value: undefined,
note: undefined,
talabBedehi: false,
direction: 'charge',
amountAbs: undefined
}
}
export function buildChargePayload(form: Charge): Charge {
const amount = Math.abs(Number(form.amountAbs) || 0)
const signed = form.direction === 'discharge' ? -amount : amount
return {
value: signed,
note: form.note,
customer_id: form.customer_id,
talabBedehi: form.talabBedehi === true
}
}
export function walletChargeTitle(
variant: 'money' | 'gold',
direction: WalletChargeDirection = 'charge'
) {
const wallet = variant === 'money' ? 'ریالی' : 'طلایی'
const action = direction === 'discharge' ? 'دشارژ' : 'شارژ'
return `${action} کیف پول ${wallet}`
}
export function walletChargeOkText(direction: WalletChargeDirection = 'charge') {
return direction === 'discharge' ? 'ثبت دشارژ' : 'ثبت شارژ'
}
export function walletChargeSuccessMessage(direction: WalletChargeDirection = 'charge') {
return direction === 'discharge' ? 'دشارژ با موفقیت انجام شد' : 'شارژ با موفقیت انجام شد'
}
+26 -6
View File
@@ -8,6 +8,7 @@ export function getConfigApp(key: string) {
}
let storeModeFromSettings: boolean | null = null
let settingsBootstrapped = false
function isSwitchOn(value: string | undefined | null): boolean {
const v = (value ?? '').trim().toLowerCase()
@@ -18,20 +19,39 @@ export function setStoreModeFromSettings(value: boolean): void {
storeModeFromSettings = value
}
/** is_store فقط از API تنظیمات (get_settings) خوانده می‌شود — نه از get_user */
export async function initStoreModeFromSettings(): Promise<boolean> {
if (storeModeFromSettings !== null) return storeModeFromSettings
async function bootstrapSettingsFromApi(): Promise<void> {
if (settingsBootstrapped) return
try {
const { getConfiguration } = await import('@/api/configuration')
const { parseMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
const rows = await getConfiguration()
const row = Array.isArray(rows) ? rows.find((item) => item.key === 'is_store') : null
storeModeFromSettings = row ? isSwitchOn(row.value) : false
const list = Array.isArray(rows) ? rows : []
const isStoreRow = list.find((item) => item.key === 'is_store')
const mainWalletRow = list.find((item) => item.key === 'main_wallet_products')
storeModeFromSettings = isStoreRow ? isSwitchOn(isStoreRow.value) : false
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
setCachedMainWalletProductIds(parseMainWalletProductIds(mainWalletRow?.value))
} catch {
storeModeFromSettings = false
const { setCachedMainWalletProductIds } = await import('@/components/mobile/utils/wallet')
setCachedMainWalletProductIds([])
} finally {
settingsBootstrapped = true
}
}
return storeModeFromSettings
/** is_store و main_wallet_products از API تنظیمات — نه از get_user */
export async function initStoreModeFromSettings(): Promise<boolean> {
if (storeModeFromSettings !== null) return storeModeFromSettings
await bootstrapSettingsFromApi()
return storeModeFromSettings === true
}
export async function initWalletSettingsFromApi(): Promise<void> {
await bootstrapSettingsFromApi()
}
export function isStoreApp(): boolean {