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
@@ -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>