Fix boursecu asset info modals with per-product copper breakdown.
Show total product wallet sum alongside the clicked product inventory in readable multi-line modals on mobile and desktop. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+166
-29
@@ -105,21 +105,21 @@ export interface HomeAssetRow {
|
||||
info: HomeAssetRowInfo
|
||||
/** boursecu — متن مودال توضیحات (info) */
|
||||
modalText?: string
|
||||
/** boursecu — عنوان مودال (مثلاً کل دارایی مس) */
|
||||
modalTitle?: string
|
||||
/** boursecu — محتوای چندخطی مودال */
|
||||
modalContent?: string
|
||||
}
|
||||
|
||||
function formatInventoryCardProductLabel(card: WalletInventoryCard): string {
|
||||
return `دارایی ${card.title}`
|
||||
}
|
||||
|
||||
function formatBoursecuProductModalText(card: WalletInventoryCard): string {
|
||||
return `${formatInventoryCardProductLabel(card)} = موجودی ${card.title}`
|
||||
}
|
||||
|
||||
/** boursecu — متن مودال برای ردیفهای metal_totals */
|
||||
export function formatBoursecuMetalModalText(metal: WalletMetalTotal): string {
|
||||
switch (metal.metal_id) {
|
||||
case METAL_COPPER:
|
||||
return 'مجموع دارایی مس = جمع کاتد و مفتول و شمش'
|
||||
return getTotalMetalLabel(METAL_COPPER)
|
||||
case METAL_GOLD:
|
||||
return 'دارایی شمش مس = موجودی شمش مس'
|
||||
case METAL_SILVER:
|
||||
@@ -129,6 +129,121 @@ export function formatBoursecuMetalModalText(metal: WalletMetalTotal): string {
|
||||
}
|
||||
}
|
||||
|
||||
/** boursecu — جمع موجودی کاتد، مفتول و شمش از کارتهای دارایی صفحه اصلی */
|
||||
function sumBoursecuHomeProductInventories(
|
||||
inventoryCards: WalletInventoryCard[],
|
||||
countProducts: WalletInventoryCard[]
|
||||
): number {
|
||||
let sum = 0
|
||||
|
||||
for (const card of inventoryCards) {
|
||||
if (card.display_type === 'count') {
|
||||
continue
|
||||
}
|
||||
sum += Number(card.quantity ?? 0)
|
||||
}
|
||||
|
||||
for (const card of countProducts) {
|
||||
const quantity = Number(card.quantity ?? 0)
|
||||
const unitWeight = Number(card.unit_weight ?? 0)
|
||||
if (unitWeight > 0) {
|
||||
sum += quantity * unitWeight
|
||||
continue
|
||||
}
|
||||
|
||||
if (card.unit?.includes('کیلو')) {
|
||||
sum += quantity
|
||||
}
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
|
||||
type BoursecuModalProduct = {
|
||||
title: string
|
||||
quantity: number
|
||||
unit: string
|
||||
}
|
||||
|
||||
function toBoursecuModalProduct(card: WalletInventoryCard): BoursecuModalProduct {
|
||||
return {
|
||||
title: card.title,
|
||||
quantity: Number(card.quantity ?? 0),
|
||||
unit: card.unit ?? (card.display_type === 'count' ? 'عدد' : 'کیلوگرم'),
|
||||
}
|
||||
}
|
||||
|
||||
function resolveBoursecuMetalModalProduct(
|
||||
metal: WalletMetalTotal,
|
||||
countProducts: WalletInventoryCard[]
|
||||
): BoursecuModalProduct {
|
||||
const countCard =
|
||||
countProducts.find((card) => Number(card.metal_id) === metal.metal_id) ??
|
||||
countProducts.find((card) => card.title?.includes('شمش'))
|
||||
|
||||
if (countCard) {
|
||||
return toBoursecuModalProduct(countCard)
|
||||
}
|
||||
|
||||
if (metal.metal_id === METAL_GOLD) {
|
||||
return {
|
||||
title: 'شمش مس',
|
||||
quantity: Number(metal.total_weight ?? 0),
|
||||
unit: 'عدد',
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: metal.label,
|
||||
quantity: Number(metal.total_weight ?? 0),
|
||||
unit: metal.unit ?? 'کیلوگرم',
|
||||
}
|
||||
}
|
||||
|
||||
/** boursecu — جزئیات کل دارایی مس در مودال info */
|
||||
export function formatBoursecuCopperAssetsModalContent(
|
||||
metal: WalletMetalTotal,
|
||||
inventoryCards: WalletInventoryCard[],
|
||||
countProducts: WalletInventoryCard[],
|
||||
product: BoursecuModalProduct
|
||||
): string {
|
||||
const weightUnit = metal.unit || 'کیلوگرم'
|
||||
const productWeight = usePriceWithoutType(
|
||||
sumBoursecuHomeProductInventories(inventoryCards, countProducts),
|
||||
false
|
||||
)
|
||||
const clickedQuantity = usePriceWithoutType(product.quantity, false)
|
||||
|
||||
return [
|
||||
`مجموع کیف محصولات: ${productWeight} ${weightUnit}`,
|
||||
`موجودی ${product.title}: ${clickedQuantity} ${product.unit}`,
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
function withBoursecuCopperModal(
|
||||
row: Omit<HomeAssetRow, 'modalTitle' | 'modalContent'>,
|
||||
copperTotal: WalletMetalTotal | undefined,
|
||||
inventoryCards: WalletInventoryCard[],
|
||||
countProducts: WalletInventoryCard[],
|
||||
product: BoursecuModalProduct
|
||||
): HomeAssetRow {
|
||||
if (!copperTotal) {
|
||||
return row
|
||||
}
|
||||
|
||||
return {
|
||||
...row,
|
||||
metal: copperTotal,
|
||||
modalTitle: getTotalMetalLabel(METAL_COPPER),
|
||||
modalContent: formatBoursecuCopperAssetsModalContent(
|
||||
copperTotal,
|
||||
inventoryCards,
|
||||
countProducts,
|
||||
product
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
function findMetalTotalById(metalTotals: WalletMetalTotal[], metalId: number) {
|
||||
return metalTotals.find((metal) => metal.metal_id === metalId)
|
||||
}
|
||||
@@ -158,20 +273,28 @@ export function buildBoursecuHomeAssetRows(
|
||||
const metalTotals = summary.metal_totals ?? []
|
||||
const inventoryCards = summary.inventory_cards ?? []
|
||||
const countProducts = summary.count_products ?? []
|
||||
const copperTotal = findMetalTotalById(metalTotals, METAL_COPPER)
|
||||
|
||||
for (const card of inventoryCards) {
|
||||
if (card.display_type === 'count') {
|
||||
continue
|
||||
}
|
||||
|
||||
rows.push({
|
||||
id: `inventory-${card.product_id}`,
|
||||
label: formatInventoryCardProductLabel(card),
|
||||
value: formatInventoryCardValue(card),
|
||||
metal: findMetalTotalById(metalTotals, card.metal_id),
|
||||
info: 'metal',
|
||||
modalText: formatBoursecuProductModalText(card),
|
||||
})
|
||||
rows.push(
|
||||
withBoursecuCopperModal(
|
||||
{
|
||||
id: `inventory-${card.product_id}`,
|
||||
label: formatInventoryCardProductLabel(card),
|
||||
value: formatInventoryCardValue(card),
|
||||
metal: findMetalTotalById(metalTotals, card.metal_id),
|
||||
info: 'metal',
|
||||
},
|
||||
copperTotal,
|
||||
inventoryCards,
|
||||
countProducts,
|
||||
toBoursecuModalProduct(card)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
for (const metal of metalTotals) {
|
||||
@@ -179,25 +302,39 @@ export function buildBoursecuHomeAssetRows(
|
||||
continue
|
||||
}
|
||||
|
||||
rows.push({
|
||||
id: `metal-${metal.metal_id}`,
|
||||
label: resolveMetalAssetsDisplayLabel(metal, true),
|
||||
value: formatBoursecuMetalRowValue(metal),
|
||||
metal,
|
||||
info: 'metal',
|
||||
modalText: formatBoursecuMetalModalText(metal),
|
||||
})
|
||||
rows.push(
|
||||
withBoursecuCopperModal(
|
||||
{
|
||||
id: `metal-${metal.metal_id}`,
|
||||
label: resolveMetalAssetsDisplayLabel(metal, true),
|
||||
value: formatBoursecuMetalRowValue(metal),
|
||||
metal,
|
||||
info: 'metal',
|
||||
},
|
||||
copperTotal,
|
||||
inventoryCards,
|
||||
countProducts,
|
||||
resolveBoursecuMetalModalProduct(metal, countProducts)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
for (const card of countProducts) {
|
||||
rows.push({
|
||||
id: `count-${card.product_id}`,
|
||||
label: formatInventoryCardProductLabel(card),
|
||||
value: formatInventoryCardValue(card),
|
||||
metal: findMetalTotalById(metalTotals, card.metal_id),
|
||||
info: 'metal',
|
||||
modalText: formatBoursecuProductModalText(card),
|
||||
})
|
||||
rows.push(
|
||||
withBoursecuCopperModal(
|
||||
{
|
||||
id: `count-${card.product_id}`,
|
||||
label: formatInventoryCardProductLabel(card),
|
||||
value: formatInventoryCardValue(card),
|
||||
metal: findMetalTotalById(metalTotals, card.metal_id),
|
||||
info: 'metal',
|
||||
},
|
||||
copperTotal,
|
||||
inventoryCards,
|
||||
countProducts,
|
||||
toBoursecuModalProduct(card)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
rows.push({
|
||||
|
||||
Reference in New Issue
Block a user