Show boursecu assets per product from wallet API and scale day range for maftol.

Fix rules paragraph alignment so Persian text does not stretch with justify.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-15 11:01:57 +03:30
co-authored by Cursor
parent b364a82892
commit f0c1bb6c51
11 changed files with 277 additions and 31 deletions
@@ -1,14 +1,34 @@
<template>
<div :class="plain ? 'py-2' : 'bg-primary rounded-lg p-2 py-3 mt-2'">
<div
v-if="meta?.has_count_based_products"
v-if="!boursecuLayout && meta?.has_count_based_products"
:class="rowClass"
class="flex justify-center w-full z-20"
>
محصولات:
<div class="text-l mr-2 font-bold">{{ countBasedInventory }} عدد</div>
</div>
<template v-if="meta?.single_metal && primaryMetalTotal">
<template v-if="boursecuAssetRows.length">
<div
v-for="(row, index) in boursecuAssetRows"
:key="row.id"
:class="[rowClass, index > 0 ? 'mt-2' : '']"
class="flex justify-center w-full z-20"
>
{{ row.label }}:
<div class="text-l mr-2 font-bold">{{ row.value }}</div>
<BasicIcon
v-if="row.info !== 'none'"
icon="vuesax-linear:info-circle"
size="18"
:color="iconColor"
@click="handleRowInfo(row)"
/>
</div>
</template>
<template v-else-if="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>
@@ -20,7 +40,8 @@
/>
</div>
</template>
<template v-else>
<template v-else-if="!boursecuLayout">
<div
v-for="(metal, index) in metalTotals"
:key="metal.metal_id"
@@ -37,17 +58,18 @@
@click="$emit('openGoldModal', metal)"
/>
</div>
<div :class="[rowClass, 'mt-2']" class="flex justify-center w-full z-20">
دارایی ریالی:
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(totalRialValue) }} ریال</div>
<BasicIcon
icon="vuesax-linear:info-circle"
size="18"
:color="iconColor"
@click="$emit('openRialModal')"
/>
</div>
</template>
<div :class="[rowClass, 'mt-2']" class="flex justify-center w-full z-20">
دارایی ریالی:
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(totalRialValue) }} ریال</div>
<BasicIcon
icon="vuesax-linear:info-circle"
size="18"
:color="iconColor"
@click="$emit('openRialModal')"
/>
</div>
</div>
</template>
@@ -57,29 +79,36 @@ import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { usePriceWithoutType } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
import { resolveSummaryMetalWeight } from '@/utils/productAssets'
import {
buildBoursecuHomeAssetRows,
resolveSummaryMetalWeight,
type HomeAssetRow,
} from '@/utils/productAssets'
const props = withDefaults(
defineProps<{
plain?: boolean
boursecuLayout?: boolean
}>(),
{ plain: false }
{ plain: false, boursecuLayout: false }
)
/** Display-only — wallet assets are loaded once in useHomePageData.initHomePageData() */
const { assetsSummary } = useWalletAssets()
defineEmits<{
const emit = defineEmits<{
openGoldModal: [metal: WalletMetalTotal]
openRialModal: []
}>()
const { assetsSummary } = useWalletAssets()
const rowClass = computed(() => (props.plain ? 'text-primary' : 'text-tertiary'))
const iconColor = computed(() => (props.plain ? 'primary' : 'tertiary'))
const meta = computed(() => assetsSummary.value?.meta)
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const primaryMetalTotal = computed(() => metalTotals.value[0])
const boursecuAssetRows = computed(() =>
props.boursecuLayout ? buildBoursecuHomeAssetRows(assetsSummary.value) : []
)
const totalRialValue = computed(() => assetsSummary.value?.total_rial_value ?? 0)
const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? [])
const countBasedInventory = computed(() =>
@@ -89,4 +118,15 @@ const countBasedInventory = computed(() =>
function formatMetalTotal(metal: WalletMetalTotal) {
return `${resolveSummaryMetalWeight(metal, inventoryCards.value)}${metal.unit}`
}
function handleRowInfo(row: HomeAssetRow) {
if (row.info === 'rial') {
emit('openRialModal')
return
}
if (row.metal) {
emit('openGoldModal', row.metal)
}
}
</script>
+17 -3
View File
@@ -32,21 +32,35 @@
<script setup lang="ts">
import { computed } from 'vue'
import { getTradeBuyPrice, getTradeSellPrice } from '@/utils/price'
import { usePriceWithoutType } from '../../../../utils/usePrice'
import type { ChartMetalType } from '../composables/usePriceChart'
import { resolveMetalDayRangePrices } from '../composables/usePriceChart'
const props = withDefaults(
defineProps<{
price: any
layout?: 'default' | 'boursecu'
variant?: 'mobile' | 'desktop'
selectedMetal?: ChartMetalType
maftolRatio?: number
}>(),
{
layout: 'default',
variant: 'mobile',
selectedMetal: 'katod',
maftolRatio: 0,
}
)
const highPrice = computed(() => props.price?.up?.buy ?? getTradeBuyPrice(props.price))
const lowPrice = computed(() => props.price?.up?.sell ?? getTradeSellPrice(props.price))
const rangePrices = computed(() =>
resolveMetalDayRangePrices({
price: props.price,
metal: props.selectedMetal,
isBoursecuLayout: props.layout === 'boursecu',
maftolRatio: props.maftolRatio,
})
)
const highPrice = computed(() => rangePrices.value.high)
const lowPrice = computed(() => rangePrices.value.low)
</script>