fix some bugs

This commit is contained in:
2026-07-01 22:28:25 +03:30
parent 2feeefc26f
commit e097f6b2bb
24 changed files with 579 additions and 189 deletions
+6 -13
View File
@@ -36,11 +36,6 @@
<div v-else class="w-full h-[88px]">
<GoldSkeleton class="w-full" />
</div>
<div v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
class="text-red text-xs flex gap-1 items-center justify-center my-2">
<Icon icon="vuesax-linear:info-circle" size="16" />
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
</div>
</a-spin>
<a-form :model="form" class="!mt-5" name="basic" @finish="okConfirm()">
<div class="border-gray-200 border-1 rounded-xl p-5 h-58 relative">
@@ -236,7 +231,7 @@ import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@
import type { Product } from '@/models/products'
import { useFundUserStore } from '@/store/fundStore'
import {useConfigStore} from "@/store/configStore";
import { calcFeeInGrams } from '@/utils/serviceFee'
import { calcFeeInGrams, calcPayablePriceRial, calcSellGoldDebit, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee'
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
import { getCashWalletBalance } from '@/utils/productAssets'
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
@@ -315,8 +310,9 @@ const finalPrice = computed(() => {
})
const payablePrice = computed(() =>
isBuy.value ? finalPrice.value + feeInRial.value : finalPrice.value - feeInRial.value
calcPayablePriceRial(finalPrice.value, feeInRial.value, isBuy.value)
)
const sellGoldDebit = computed(() => calcSellGoldDebit(form.value?.goldValue, feeInGrams.value))
const feeInGrams = computed(() => calcFeeInGrams(form.value?.goldValue))
const unitPrice = computed(() =>
(props?.ProductItem?.price_profit ?? 0) + (props?.ProductItem?.price ?? 0)
@@ -332,7 +328,8 @@ const disableTransaction = computed(() =>
form.value?.goldCash === '' ||
form.value?.goldCash === undefined ||
(isBuy.value ? (form.value?.goldCash ?? 0) < 500000 : (form.value?.goldValue ?? 0) < 0.001) ||
(!isBuy.value && form.value.goldValue > walletStore?.walletInfo?.gold) ||
(!isBuy.value && sellGoldDebit.value > (walletStore?.walletInfo?.gold ?? 0)) ||
(isBuy.value && payablePrice.value > cashWalletBalance.value) ||
!lastPrice.value ||
(isBuy.value ? getTradeBuyPrice(lastPrice.value) <= 0 : getTradeSellPrice(lastPrice.value) <= 0))
@@ -436,6 +433,7 @@ onMounted(async () => {
break
}
await initPrice()
await loadServiceFeeFromSettings()
/* await initSellTable()
await initBuyTable()*/
})
@@ -499,11 +497,6 @@ const unitCashCalculator = computed(() => {
return cashWalletBalance.value / 100
})
const limitedPrice = computed(() => {
if (walletStore.limitedPrice)
return walletStore?.limitedPrice[0]
})
/*function calculateCash(val: number) {
priceErrorVisible.value = false
// console.log(val)
+53 -19
View File
@@ -56,11 +56,6 @@
<div v-else class="w-full h-[88px]">
<GoldSkeleton class="w-full" />
</div>
<div v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
class="text-red text-xs flex gap-1 items-center justify-center my-2">
<Icon icon="vuesax-linear:info-circle" size="16" />
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
</div>
</a-spin>
<a-form :model="form" class="!mt-5" name="basic" @finish="okConfirm()">
<div class="border-gray-200 border-1 rounded-xl p-5 gold-form-card relative">
@@ -137,13 +132,14 @@
<div v-else>{{ !isBuy ? 'فروش' : 'خرید' }}</div>
</div>
</BasicButton>
<div v-if="!isBuy && form.goldValue > productWalletBalance"
<div v-if="!isBuy && sellGoldDebit > productWalletBalance"
class="text-red-700 text-xs font-bold mt-2">
مقدار {{ weightUnit }} وارد شده جهت فروش ({{ form.goldValue }}{{ weightUnit }}) بیشتر از مقدار موجودی شما
({{ productWalletBalance }}{{ weightUnit }}) می باشد.
<span v-if="feeDeductFromGold"> (با احتساب {{ feeInGrams }}{{ weightUnit }} کارمزد، مجموعاً {{ sellGoldDebit }}{{ weightUnit }} کسر می‌شود)</span>
</div>
<!-- <div>{{form?.goldValue? true: false}}</div>-->
<div v-if="isBuy ? (form?.goldCash > cashWalletBalance) : false"
<div v-if="isBuy ? (payablePrice > cashWalletBalance) : false"
class="text-red-700 text-xs font-bold mt-2">
موجودی کیف پول ناکافی می باشد.
</div>
@@ -196,6 +192,20 @@
</div>
</div>
<div >(معادل {{ equivalentPrice }} ریال)</div>
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
<div>طلا دریافتی:</div>
<div class="flex items-center">
<div class="font-bold">{{ form.goldValue }}</div>
<div class="text-xs mr-1">{{ weightUnit }} (دقیق — کارمزد از ریال)</div>
</div>
</div>
<div v-if="!isBuy && feeDeductFromGold" class="flex justify-between mt-3">
<div>کسر از کیف طلا:</div>
<div class="flex items-center">
<div class="font-bold">{{ sellGoldDebit }}</div>
<div class="text-xs mr-1">{{ weightUnit }}</div>
</div>
</div>
<div class="flex justify-between mt-3">
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}</div>
<div class="flex items-center">
@@ -237,6 +247,20 @@
</div>
</div>
<div>(معادل {{ equivalentPrice }} ریال)</div>
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
<div>طلا دریافتی:</div>
<div class="flex items-center">
<div class="font-bold">{{ form.goldValue }}</div>
<div class="text-xs mr-1">{{ weightUnit }} (دقیق — کارمزد از ریال)</div>
</div>
</div>
<div v-if="!isBuy && feeDeductFromGold" class="flex justify-between mt-3">
<div>کسر از کیف طلا:</div>
<div class="flex items-center">
<div class="font-bold">{{ sellGoldDebit }}</div>
<div class="text-xs mr-1">{{ weightUnit }}</div>
</div>
</div>
<div class="flex justify-between mt-3">
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}</div>
<div class="flex items-center">
@@ -306,7 +330,7 @@ import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@
import type { Product } from '@/models/products'
import { useFundUserStore } from '@/store/fundStore'
import {useConfigStore} from "@/store/configStore";
import { calcFeeInGrams, loadServiceFeeFromSettings } from '@/utils/serviceFee'
import { calcFeeInGrams, calcOrderGoldAmount, calcPayablePriceRial, calcSellGoldDebit, calcSellTargetCash, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee'
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
@@ -411,13 +435,22 @@ const unitPrice = computed(() => {
}
return isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value)
})
const feeInGrams = computed(() => calcFeeInGrams(form.value?.goldValue))
const finalPrice = computed(() => (form.value?.goldValue ?? 0) * unitPrice.value)
const orderGoldAmount = computed(() =>
calcOrderGoldAmount(form.value?.goldValue, form.value?.goldCash, unitPrice.value, isBuy.value)
)
const feeInGrams = computed(() => calcFeeInGrams(orderGoldAmount.value))
const finalPrice = computed(() => orderGoldAmount.value * unitPrice.value)
const feeInRial = computed(() => unitPrice.value * feeInGrams.value)
const equivalentPrice = computed(() => usePriceWithoutType(feeInRial.value.toFixed(0)))
const payablePrice = computed(() =>
isBuy.value ? finalPrice.value + feeInRial.value : finalPrice.value - feeInRial.value
calcPayablePriceRial(
finalPrice.value,
feeInRial.value,
isBuy.value,
!isBuy.value ? form.value?.goldCash : undefined
)
)
const sellGoldDebit = computed(() => calcSellGoldDebit(orderGoldAmount.value, feeInGrams.value))
const minOrderCash = computed(() => productMinOrderCash(props.ProductItem, isBuy.value))
const maxOrderCash = computed(() => productMaxOrderCash(props.ProductItem))
@@ -444,7 +477,8 @@ const disableTransaction = computed(() =>
: (form.value?.goldValue ?? 0) < 0.001)) ||
(maxOrderCash.value != null && (form.value?.goldCash ?? 0) > maxOrderCash.value) ||
cashValidationMessage.value !== '' ||
(!isBuy.value && form.value.goldValue > walletStore?.walletInfo?.gold) ||
(!isBuy.value && sellGoldDebit.value > productWalletBalance.value) ||
(isBuy.value && payablePrice.value > cashWalletBalance.value) ||
priceUnavailable.value)
function refreshTable() {
@@ -609,11 +643,6 @@ const unitCashCalculator = computed(() => {
return cashWalletBalance.value / 100
})
const limitedPrice = computed(() => {
if (walletStore.limitedPrice)
return walletStore?.limitedPrice[0]
})
function syncFormWithLatestPrice() {
const unit = unitPrice.value
if (!unit || Number.isNaN(unit)) return
@@ -661,7 +690,11 @@ function calculateGold(val: number) {
priceErrorVisible.value = false
}
} else if (val) {
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit)))
if (!isBuy.value && feeDeductFromGold.value) {
form.value.goldValue = parseFloat((val / unit).toFixed(6))
} else {
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit)))
}
priceErrorVisible.value = parseInt(String(finalPrice.value)) > 0
} else if (val.toString() === '') {
form.value.goldValue = undefined
@@ -744,7 +777,8 @@ async function ok() {
await createOrder({
direction: isBuy.value ? 1 : 2,
price: Math.round(unitPrice.value),
amount: form.value.goldValue ?? 0,
amount: orderGoldAmount.value,
target_cash: calcSellTargetCash(form.value.goldCash, form.value.goldValue, unitPrice.value),
abshode_id: props.ProductItem?.id,
})
confirmAction.value = false
@@ -3,19 +3,21 @@
<div
v-if="!boursecuLayout && meta?.has_count_based_products"
:class="rowClass"
class="flex justify-center w-full z-20"
class="flex justify-center w-full z-20 mb-2"
>
محصولات:
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(countBasedInventory, false) }} عدد</div>
</div>
<PortfolioOverview v-if="!boursecuLayout" variant="mobile" />
<BoursecuAssetsSummary
v-if="boursecuLayout"
v-else-if="boursecuLayout"
variant="mobile"
icon-color="primary"
/>
<template v-else-if="meta?.single_metal && primaryMetalTotal">
<template v-else-if="showLegacyRows && meta?.single_metal && primaryMetalTotal">
<div :class="[rowClass, meta?.has_count_based_products ? 'mt-2' : '']" class="flex justify-center w-full z-20">
{{ primaryMetalTotal.label }}:
<div class="text-l mr-2 font-bold">{{ formatMetalTotal(primaryMetalTotal) }}</div>
@@ -39,7 +41,7 @@
</div>
</template>
<template v-else-if="!boursecuLayout">
<template v-else-if="showLegacyRows && !boursecuLayout">
<div
v-for="(metal, index) in metalTotals"
:key="metal.metal_id"
@@ -75,6 +77,7 @@
import { computed } from 'vue'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import BoursecuAssetsSummary from './BoursecuAssetsSummary.vue'
import PortfolioOverview from './PortfolioOverview.vue'
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
@@ -116,6 +119,7 @@ const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? []
const countBasedInventory = computed(() =>
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0)
)
const showLegacyRows = computed(() => !assetsSummary.value?.portfolio)
function formatMetalTotal(metal: WalletMetalTotal) {
return `${formatWeightAmount(resolveSummaryMetalWeight(metal, inventoryCards.value))}${metal.unit}`
@@ -42,6 +42,21 @@
is-line
:value="usePrice(totalRialValue)"
/>
<template v-if="portfolioInsight?.unrealized_profit_rial != null">
<a-divider class="!my-1" />
<BasicInfoItem
class="flex justify-between"
title="میانگین قیمت خرید"
is-line
:value="usePrice(portfolioInsight.average_buy_price ?? 0)"
/>
<BasicInfoItem
class="flex justify-between"
title="سود/زیان تحقق‌نیافته"
is-line
:value="profitSheetLabel"
/>
</template>
</div>
</div>
</div>
@@ -56,7 +71,7 @@ import BasicInfoItem from '@/components/BasicPacks/BasicInfoItem.vue'
import { usePrice } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
import { formatInventoryCardValue, assetSheetInventoryCards, resolveAssetsRialValue } from '@/utils/productAssets'
import { formatInventoryCardValue, assetSheetInventoryCards, resolveAssetsRialValue, formatPortfolioProfitPercent, formatPortfolioProfitText } from '@/utils/productAssets'
import { getTradeBuyPrice, lastPrice } from '@/utils/price'
const props = defineProps<{
@@ -83,6 +98,13 @@ const metalRialValue = computed(() =>
resolveAssetsRialValue(assetsSummary.value, getTradeBuyPrice(lastPrice.value))
)
const totalRialValue = computed(() => cashWallet.value + metalRialValue.value)
const portfolioInsight = computed(() => assetsSummary.value?.portfolio)
const profitSheetLabel = computed(() => {
const profit = portfolioInsight.value?.unrealized_profit_rial
if (profit == null) return '-'
const pct = formatPortfolioProfitPercent(portfolioInsight.value?.unrealized_profit_percent)
return `${formatPortfolioProfitText(profit)}${pct ? ` (${pct})` : ''}`
})
watch(
() => props.show,
@@ -0,0 +1,259 @@
<template>
<section :class="rootClass">
<header class="portfolio-overview__header">
<span class="portfolio-overview__eyebrow">کل دارایی شما</span>
<p class="portfolio-overview__total">
{{ usePriceWithoutType(totalRial) }}
<span class="portfolio-overview__unit">ریال</span>
</p>
</header>
<div
v-if="hasProfitInsight"
class="portfolio-overview__profit"
:class="{
'portfolio-overview__profit--up': profitTone === 'profit',
'portfolio-overview__profit--down': profitTone === 'loss',
}"
>
<span class="portfolio-overview__profit-amount">{{ profitText }}</span>
<span v-if="profitPercent" class="portfolio-overview__profit-percent">{{ profitPercent }}</span>
<span class="portfolio-overview__profit-hint">سود/زیان تحقق‌نیافته طلا</span>
</div>
<div class="portfolio-overview__grid">
<article class="portfolio-overview__tile">
<span class="portfolio-overview__tile-label">ارزش طلا</span>
<strong class="portfolio-overview__tile-value">{{ usePriceWithoutType(metalRial) }} ریال</strong>
<span v-if="goldWeight > 0" class="portfolio-overview__tile-sub">
{{ formatWeightAmount(goldWeight) }}{{ weightUnit }}
</span>
</article>
<article class="portfolio-overview__tile">
<span class="portfolio-overview__tile-label">موجودی نقد</span>
<strong class="portfolio-overview__tile-value">{{ usePriceWithoutType(cashRial) }} ریال</strong>
<span class="portfolio-overview__tile-sub">کیف پول ریالی</span>
</article>
</div>
<p v-if="hasProfitInsight && averageBuyPrice" class="portfolio-overview__footnote">
بر اساس میانگین خرید {{ usePriceWithoutType(averageBuyPrice) }} ریال و قیمت فعلی
{{ usePriceWithoutType(liveGoldPrice) }} ریال
</p>
</section>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useWalletAssets } from '@/composables/useWalletAssets'
import {
formatPortfolioProfitLabel,
formatPortfolioProfitPercent,
formatPortfolioProfitText,
resolveAssetsRialValue,
} from '@/utils/productAssets'
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
import { getTradeBuyPrice, lastPrice } from '@/utils/price'
const props = withDefaults(
defineProps<{
variant?: 'mobile' | 'desktop'
}>(),
{ variant: 'mobile' }
)
const { assetsSummary } = useWalletAssets()
const portfolio = computed(() => assetsSummary.value?.portfolio)
const weightUnit = computed(() => assetsSummary.value?.meta?.weight_unit || 'گرم')
const totalRial = computed(() =>
Number(portfolio.value?.total_rial_value ?? assetsSummary.value?.total_rial_value ?? 0)
)
const cashRial = computed(() =>
Number(portfolio.value?.cash_rial ?? assetsSummary.value?.cash_wallet ?? 0)
)
const metalRial = computed(() => {
const fromPortfolio = Number(portfolio.value?.metal_rial_value ?? 0)
if (fromPortfolio > 0) return fromPortfolio
return resolveAssetsRialValue(assetsSummary.value, getTradeBuyPrice(lastPrice.value))
})
const goldWeight = computed(() => Number(portfolio.value?.gold_weight ?? 0))
const averageBuyPrice = computed(() => portfolio.value?.average_buy_price ?? null)
const liveGoldPrice = computed(() => Number(portfolio.value?.live_gold_price ?? 0))
const hasProfitInsight = computed(() => portfolio.value?.unrealized_profit_rial != null)
const profitTone = computed(() => formatPortfolioProfitLabel(portfolio.value?.unrealized_profit_rial))
const profitText = computed(() => formatPortfolioProfitText(portfolio.value?.unrealized_profit_rial))
const profitPercent = computed(() =>
formatPortfolioProfitPercent(portfolio.value?.unrealized_profit_percent)
)
const rootClass = computed(() => [
'portfolio-overview',
`portfolio-overview--${props.variant}`,
])
</script>
<style scoped lang="less">
.portfolio-overview {
border-radius: 14px;
padding: 14px 16px;
background: linear-gradient(145deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.06));
border: 1px solid rgba(255, 255, 255, 0.22);
color: #fff;
}
.portfolio-overview--desktop {
margin-bottom: 16px;
padding: 20px 22px;
background: #fff;
border: 1px solid rgba(15, 23, 42, 0.06);
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
color: #111827;
}
.portfolio-overview__header {
margin-bottom: 12px;
}
.portfolio-overview__eyebrow {
display: block;
font-size: 12px;
font-weight: 600;
opacity: 0.85;
}
.portfolio-overview--desktop .portfolio-overview__eyebrow {
color: #6b7280;
opacity: 1;
}
.portfolio-overview__total {
margin: 4px 0 0;
font-size: 1.65rem;
font-weight: 800;
line-height: 1.2;
letter-spacing: -0.02em;
}
.portfolio-overview__unit {
font-size: 0.85rem;
font-weight: 600;
margin-right: 4px;
opacity: 0.9;
}
.portfolio-overview__profit {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
padding: 8px 10px;
border-radius: 10px;
margin-bottom: 12px;
background: rgba(255, 255, 255, 0.12);
font-size: 13px;
font-weight: 700;
}
.portfolio-overview--desktop .portfolio-overview__profit {
background: #f9fafb;
}
.portfolio-overview__profit--up {
color: #bbf7d0;
}
.portfolio-overview--desktop .portfolio-overview__profit--up {
color: #027a48;
background: #ecfdf3;
}
.portfolio-overview__profit--down {
color: #fecaca;
}
.portfolio-overview--desktop .portfolio-overview__profit--down {
color: #b42318;
background: #fef3f2;
}
.portfolio-overview__profit-percent {
direction: ltr;
unicode-bidi: isolate;
font-variant-numeric: tabular-nums;
}
.portfolio-overview__profit-hint {
width: 100%;
font-size: 11px;
font-weight: 500;
opacity: 0.85;
}
.portfolio-overview--desktop .portfolio-overview__profit-hint {
color: #6b7280;
opacity: 1;
}
.portfolio-overview__grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.portfolio-overview__tile {
padding: 10px 12px;
border-radius: 10px;
background: rgba(0, 0, 0, 0.12);
}
.portfolio-overview--desktop .portfolio-overview__tile {
background: #f6f7f9;
}
.portfolio-overview__tile-label {
display: block;
font-size: 11px;
font-weight: 600;
opacity: 0.85;
margin-bottom: 4px;
}
.portfolio-overview--desktop .portfolio-overview__tile-label {
color: #6b7280;
opacity: 1;
}
.portfolio-overview__tile-value {
display: block;
font-size: 14px;
font-weight: 700;
line-height: 1.35;
}
.portfolio-overview__tile-sub {
display: block;
margin-top: 4px;
font-size: 11px;
opacity: 0.8;
}
.portfolio-overview--desktop .portfolio-overview__tile-sub {
color: #9ca3af;
opacity: 1;
}
.portfolio-overview__footnote {
margin: 10px 0 0;
font-size: 11px;
line-height: 1.6;
opacity: 0.8;
}
.portfolio-overview--desktop .portfolio-overview__footnote {
color: #6b7280;
opacity: 1;
}
</style>
@@ -32,7 +32,6 @@ export interface HomePageContext {
homePageLoading: ReturnType<typeof useHomePageLoading>['homePageLoading']
isGaroosi: ReturnType<typeof computed<boolean>>
bannerEnabled: ReturnType<typeof computed<boolean>>
limitedPrice: ReturnType<typeof computed>
showClosedMessage: ReturnType<typeof computed<boolean>>
closedMessage: ReturnType<typeof computed>
mainActions: ReturnType<typeof computed<HomeActionItem[]>>
@@ -89,7 +88,6 @@ export function useHomePage() {
return custom || ''
})
const showClosedMessage = computed(() => !!marketClosedText.value)
const limitedPrice = computed(() => walletStore.limitedPrice?.[0])
const goldVal = computed(() => lastPrice.value?.price_last ?? 1)
const mainActions = computed<HomeActionItem[]>(() => [
@@ -199,7 +197,7 @@ export function useHomePage() {
const metalRial = resolveAssetsRialValue(summary, getTradeBuyPrice(lastPrice.value))
Modal.confirm({
title: 'دارایی ریالی',
content: renderModalLines(formatRialAssetsInfoText(cash, metalRial)),
content: renderModalLines(formatRialAssetsInfoText(cash, metalRial, summary?.portfolio)),
okText: 'متوجه شدم',
centered: true,
cancelButtonProps: { style: { display: 'none' } },
@@ -234,7 +232,6 @@ export function useHomePage() {
homePageLoading,
isGaroosi,
bannerEnabled,
limitedPrice,
showClosedMessage,
closedMessage: marketClosedText,
mainActions,
@@ -2,6 +2,7 @@
import { computed } from 'vue'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import BoursecuAssetsSummary from '../../components/BoursecuAssetsSummary.vue'
import PortfolioOverview from '../../components/PortfolioOverview.vue'
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
@@ -24,6 +25,7 @@ const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
const countBasedInventory = computed(() =>
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0),
)
const showLegacyMetrics = computed(() => !assetsSummary.value?.portfolio)
type MetricItem = {
id: string
@@ -101,7 +103,10 @@ function handleInfo(metric: MetricItem) {
icon-color="tertiary"
/>
<div v-else class="dhome-metrics">
<template v-else>
<PortfolioOverview variant="desktop" />
<div v-if="showLegacyMetrics" class="dhome-metrics">
<article v-for="metric in metrics" :key="metric.id" class="dhome-metric-tile">
<div class="dhome-metric-tile__head">
<span class="dhome-metric-tile__label">{{ metric.label }}</span>
@@ -117,5 +122,6 @@ function handleInfo(metric: MetricItem) {
</div>
<p class="dhome-metric-tile__value">{{ metric.value }}</p>
</article>
</div>
</div>
</template>
</template>
@@ -1,36 +1,15 @@
<script setup lang="ts">
import { computed, inject } from 'vue'
import { useUserStore } from '@/store/userStore'
import { usePriceWithoutType } from '@/utils/usePrice'
import { inject } from 'vue'
import { isBoursecuProject } from '@/utils/config'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { HOME_PAGE_CONTEXT_KEY } from '../../composables/useHomePage'
const ctx = inject(HOME_PAGE_CONTEXT_KEY)!
const userStore = useUserStore()
const isBoursecu = isBoursecuProject()
const showLimitedPrice = computed(
() =>
ctx.limitedPrice.value !== undefined &&
userStore.userInfo?.trade_active !== 1,
)
const limitedPriceText = computed(() =>
usePriceWithoutType(Number(ctx.limitedPrice.value?.value ?? 0)),
)
</script>
<template>
<div v-if="showLimitedPrice || ctx.showClosedMessage.value" class="dhome-alerts">
<div v-if="showLimitedPrice" class="dhome-alert dhome-alert--warning">
<BasicIcon icon="vuesax-linear:info-circle" size="14" />
<span>
حداقل مبلغ اولیه برای ثبت سفارش {{ limitedPriceText }} ریال می‌باشد.
</span>
</div>
<div v-if="!isBoursecu && ctx.showClosedMessage.value" class="dhome-alerts">
<div
v-if="!isBoursecu && ctx.showClosedMessage.value"
class="dhome-alert dhome-alert--info"
v-html="ctx.closedMessage.value"
/>
@@ -37,17 +37,17 @@ const showSkeleton = computed(() => Boolean(getToken()) && !userInfo.value)
<HomeSkeleton v-if="showSkeleton" />
<template v-if="showContent">
<section class="dhome-hero-row">
<DesktopLivePrice />
<DesktopPriceRange />
</section>
<DesktopAssetsMetrics
v-if="!ctx.isGaroosi.value"
@open-gold-modal="ctx.openGoldModal"
@open-rial-modal="ctx.openRialModal"
/>
<section class="dhome-hero-row">
<DesktopLivePrice />
<DesktopPriceRange />
</section>
<div v-if="ctx.isGaroosi.value" class="dhome-default-grid">
<div class="dhome-default-grid__main">
<DesktopDefaultActions />
@@ -11,7 +11,6 @@ export const boursecuHomeLayoutConfig: HomeLayoutConfig = {
{ id: 'assets' },
{ id: 'currentPrice' },
{ id: 'boursecuQuickActions' },
{ id: 'limitedPriceAlert' },
],
sections: [
{ id: 'marketClosed' },
@@ -4,12 +4,11 @@ import type { HomeLayoutConfig } from '../types'
export const defaultHomeLayoutConfig: HomeLayoutConfig = {
id: 'default',
wrapperClass: 'p-1 from-primary rounded-lg p-px to-transparent mt-5',
outerSections: [{ id: 'limitedPriceAlert' }],
sections: [
{ id: 'garoosiAssets' },
{ id: 'assets' },
{ id: 'mainActions' },
{ id: 'referral' },
{ id: 'assets' },
{ id: 'marketClosed' },
{ id: 'currentPrice' },
{ id: 'banners' },
@@ -1,28 +0,0 @@
<script setup lang="ts">
import { computed, inject } from 'vue'
import { useUserStore } from '@/store/userStore'
import { usePriceWithoutType } from '@/utils/usePrice'
import Icon from '@/components/BasicPacks/BasicIcon.vue'
import { HOME_PAGE_CONTEXT_KEY } from '../../composables/useHomePage'
const ctx = inject(HOME_PAGE_CONTEXT_KEY)!
const userStore = useUserStore()
const isVisible = computed(
() =>
ctx.limitedPrice.value !== undefined &&
userStore.userInfo?.trade_active !== 1
)
</script>
<template>
<div
v-if="isVisible"
class="text-red text-xs flex gap-1 items-center justify-center mb-2"
>
<Icon icon="vuesax-linear:info-circle" size="16" />
حداقل مبلغ اولیه برای ثبت سفارش
{{ usePriceWithoutType(Number(ctx.limitedPrice.value?.value ?? 0)) }}
ریال می باشد.
</div>
</template>
@@ -1,6 +1,5 @@
import type { Component } from 'vue'
import type { HomeSectionId } from '../types'
import LimitedPriceAlertSection from './LimitedPriceAlertSection.vue'
import GaroosiAssetsSection from './GaroosiAssetsSection.vue'
import MainActionsSection from './MainActionsSection.vue'
import BoursecuQuickActionsSection from './BoursecuQuickActionsSection.vue'
@@ -13,7 +12,6 @@ import PriceChartSection from './PriceChartSection.vue'
import PriceStatsSection from './PriceStatsSection.vue'
export const HOME_SECTION_COMPONENTS: Record<HomeSectionId, Component> = {
limitedPriceAlert: LimitedPriceAlertSection,
garoosiAssets: GaroosiAssetsSection,
mainActions: MainActionsSection,
boursecuQuickActions: BoursecuQuickActionsSection,
-1
View File
@@ -2,7 +2,6 @@
export type HomeLayoutId = 'default' | 'boursecu'
export type HomeSectionId =
| 'limitedPriceAlert'
| 'garoosiAssets'
| 'mainActions'
| 'boursecuQuickActions'
@@ -54,11 +54,6 @@
<div v-else class="w-full h-[88px]">
<GoldSkeleton class="w-full" />
</div>
<div v-if="limitedPrice !== undefined && userStore?.userInfo.trade_active !== 1"
class="text-red text-xs flex gap-1 items-center justify-center my-2">
<Icon icon="vuesax-linear:info-circle" size="16" />
حداقل مبلغ اولیه برای ثبت سفارش {{ usePriceWithoutType(limitedPrice.value as number ?? 0) }} ریال می باشد.
</div>
<!-- </a-spin>-->
<a-form ref="refInput" :model="form" class="!mt-5" name="basic" @finish="okConfirm()">
<div class="border-gray-200 border-1 rounded-xl p-5 relative">
@@ -722,11 +717,6 @@ const unitCashCalculator = computed(() => {
return cashWalletBalance.value / 100
})
const limitedPrice = computed(() => {
if (walletStore.limitedPrice)
return walletStore?.limitedPrice[0]
})
function handleGoldValueChange(val: string | number | undefined) {
if (val === undefined || val === null || val === '') {
form.value.goldValue = undefined