widthdraw and deposit

This commit is contained in:
2026-06-09 21:04:22 +03:30
parent 95516ee2d8
commit 689c51c27d
26 changed files with 1228 additions and 522 deletions
+6 -3
View File
@@ -1,10 +1,13 @@
import useAxios from '@/utils/useAxios'
import type { Card, Wallet, WithdrawConfirm } from '@/models/wallet'
import type {Transaction} from '@/models/transaction'
import type {Address} from "@/models/address";
import type { WalletAssetsSummary } from '@/models/walletAssets'
import type { Transaction } from '@/models/transaction'
export const getWallet = async () => await useAxios.get<Wallet>(`/customer/wallet/me`)
export const getWalletAssets = async () =>
await useAxios.get<WalletAssetsSummary>(`/customer/wallet/assets`)
export const withdraw = async (obj: Transaction): Promise<any> => {
return await useAxios.post<Transaction>(`/customer/wallet/withdraw`, obj)
}
@@ -24,5 +27,5 @@ export async function deleteCard(id: number) {
export const getActivatedCards = async () => await useAxios.get<Card[]>(`/customer/account/active`)
export const confirmCode = async (params: WithdrawConfirm): Promise<any> => {
return await useAxios.post(`/customer/wallet/withdraw/otp` , params)
return await useAxios.post(`/customer/wallet/withdraw/otp`, params)
}
+49
View File
@@ -0,0 +1,49 @@
import { computed, ref } from 'vue'
import { getProducts } from '@/api/products'
import type { Product } from '@/models/products'
import {
catalogHasCountBasedProducts,
catalogHasMeltedProducts,
getCatalogMetalIds,
isSingleMetalCatalog,
} from '@/utils/productAssets'
const catalogProducts = ref<Product[]>([])
let catalogPromise: Promise<Product[]> | null = null
export function useProductCatalog() {
async function loadCatalog(force = false) {
if (!force && catalogProducts.value.length) {
return catalogProducts.value
}
if (!force && catalogPromise) {
return catalogPromise
}
catalogPromise = getProducts()
.then((products) => {
catalogProducts.value = products ?? []
return catalogProducts.value
})
.finally(() => {
catalogPromise = null
})
return catalogPromise
}
const catalogMetalIds = computed(() => getCatalogMetalIds(catalogProducts.value))
const hasCountBasedProducts = computed(() => catalogHasCountBasedProducts(catalogProducts.value))
const hasMeltedProducts = computed(() => catalogHasMeltedProducts(catalogProducts.value))
const isSingleMetal = computed(() => isSingleMetalCatalog(catalogMetalIds.value))
return {
catalogProducts,
catalogMetalIds,
hasCountBasedProducts,
hasMeltedProducts,
isSingleMetal,
loadCatalog,
}
}
+46
View File
@@ -0,0 +1,46 @@
import { ref } from 'vue'
import { getWalletAssets } from '@/api/wallet'
import { getProducts } from '@/api/products'
import type { WalletAssetsSummary } from '@/models/walletAssets'
import { enrichInventoryCardsWithCatalog } from '@/utils/productAssets'
const assetsSummary = ref<WalletAssetsSummary | null>(null)
let assetsPromise: Promise<WalletAssetsSummary> | null = null
export function useWalletAssets() {
async function loadWalletAssets(force = false) {
if (!force && assetsSummary.value) {
return assetsSummary.value
}
if (!force && assetsPromise) {
return assetsPromise
}
assetsPromise = Promise.all([getWalletAssets(), getProducts()])
.then(([data, catalog]) => {
assetsSummary.value = {
...data,
inventory_cards: enrichInventoryCardsWithCatalog(data.inventory_cards ?? [], catalog ?? []),
count_products: enrichInventoryCardsWithCatalog(data.count_products ?? [], catalog ?? []),
}
return assetsSummary.value
})
.finally(() => {
assetsPromise = null
})
return assetsPromise
}
function clearWalletAssets() {
assetsSummary.value = null
assetsPromise = null
}
return {
assetsSummary,
loadWalletAssets,
clearWalletAssets,
}
}
+1 -1
View File
@@ -48,7 +48,7 @@ export interface User {
deleted_at?: any;
wallet: Wallet;
pwallet:PWallet;
wallets: Wallets
wallets: Wallets[]
finger_print: boolean
gold: number;
+1
View File
@@ -23,6 +23,7 @@ export interface Product {
min_order_cash?: number | null
max_order_cash?: number | null
direct_price: number | undefined
price_offset_percent?: number | null
reading_method: any
created_at: any
updated_at: any
+3 -1
View File
@@ -50,11 +50,13 @@ export interface Wallets {
number : number
owner : number
owner_type : number
product : null
product : Product | null
product_id : null | number
updated_at : string
}
export type UserWalletLine = Wallets
export interface PWallet {
id: number
owner_type: number
+43
View File
@@ -0,0 +1,43 @@
import type { ProductFile } from '@/utils/file'
export interface WalletAssetsMeta {
metal_ids: number[]
metal_count: number
has_count_based_products: boolean
has_weight_based_products: boolean
weight_unit: string
single_metal: boolean
}
export interface WalletInventoryCard {
product_id: number
title: string
group_type: string
metal_id: number
quantity: number
unit: string
display_type: 'count' | 'weight'
unit_weight?: string | null
show_in_assets: boolean
file?: ProductFile | null
}
export interface WalletMetalTotal {
metal_id: number
metal_label: string
label: string
product_weight: number
melted_weight: number
total_weight: number
unit: string
}
export interface WalletAssetsSummary {
meta: WalletAssetsMeta
cash_wallet: number
inventory_cards: WalletInventoryCard[]
count_products: WalletInventoryCard[]
metal_totals: WalletMetalTotal[]
assets_rial_value: number
total_rial_value: number
}
+3
View File
@@ -2,6 +2,7 @@ import { computed, ref } from 'vue'
import { defineStore } from 'pinia'
import { getSettings } from '@/api/configuration'
import { resolveMeltedGoldLabel, resolveMetalTypeLabel } from '@/utils/metalLabels'
import { resolveTradeWeightUnit } from '@/utils/weightUnit'
export interface AppSetting {
id?: number
@@ -60,6 +61,7 @@ export const useSettingsStore = defineStore('settings', () => {
const metalTypeSettingValue = computed(() => getSettingByKey('metal_type'))
const metalTypeLabel = computed(() => resolveMetalTypeLabel(metalTypeSettingValue.value))
const meltedGoldLabel = computed(() => resolveMeltedGoldLabel(metalTypeSettingValue.value))
const tradeWeightUnit = computed(() => resolveTradeWeightUnit(getSettingByKey('unit')))
return {
settings,
@@ -70,5 +72,6 @@ export const useSettingsStore = defineStore('settings', () => {
metalTypeSettingValue,
metalTypeLabel,
meltedGoldLabel,
tradeWeightUnit,
}
})
+10 -5
View File
@@ -10,12 +10,17 @@ export interface ProductFile {
export function getFileUrl(file?: ProductFile | null): string | null {
if (!file) return null
if (file.full_src) return file.full_src
if (file.url) return file.url
if (!file.src) return null
if (/^https?:\/\//i.test(file.src)) return file.src
for (const value of [file.full_src, file.url, file.src]) {
if (!value) continue
if (/^https?:\/\//i.test(value)) return value
}
const relative = file.src || file.full_src
if (!relative) return null
const base = baseURL.replace(/\/$/, '')
const path = file.src.replace(/^\//, '')
const path = String(relative).replace(/^\//, '')
return `${base}/${path}`
}
+2 -2
View File
@@ -164,12 +164,12 @@ if (isBuyP){
return Promise.reject(getInsufficientCashWalletMessage(groupTypeP))
}
if (!walletCash?.walletInfo?.gold && isMainMetalWalletDealMethod(methodP)){
return Promise.reject(getInsufficientGoldWalletMessage(groupTypeP))
return Promise.reject(getInsufficientGoldWalletMessage(groupTypeP, methodP))
}
if (priceP * value > walletCash?.walletInfo?.cash && isCashLikeDealMethod(methodP))
return Promise.reject(getInsufficientCashWalletMessage(groupTypeP))
if (amountP * value > walletCash?.walletInfo?.gold && isMainMetalWalletDealMethod(methodP))
return Promise.reject(getInsufficientGoldWalletMessage(groupTypeP))
return Promise.reject(getInsufficientGoldWalletMessage(groupTypeP, methodP))
else
return Promise.resolve();
}else {
+305
View File
@@ -0,0 +1,305 @@
import type { Product } from '@/models/products'
import type { UserWalletLine } from '@/models/wallet'
import type { ProductFile } from '@/utils/file'
import { getFileUrl } from '@/utils/file'
import { isCountBasedProduct, type ProductUnitSource } from '@/utils/productDealMethod'
import { isMeltedTradeGroup, normalizeProductGroupType, LEGACY_GROUP_KATOD } from '@/utils/productCategories'
import defaultImg from '@/assets/img/defaultAbshodeh.svg'
import goyImg from '@/assets/img/goyImg.svg'
import mokaabImg from '@/assets/img/mokaabImg.svg'
import sekkeImg from '@/assets/img/sekkeImg.svg'
import mesImg from '@/assets/img/mesImg.jpg'
import noghrehImg from '@/assets/img/noghrehImg.webp'
import parsianImg from '@/assets/img/parsianImg.svg'
export const METAL_GOLD = 1
export const METAL_SILVER = 2
export const METAL_COPPER = 3
const GROUP_DEFAULT_IMAGES: Record<string, string> = {
گوی: goyImg,
مکعب: mokaabImg,
سکه: sekkeImg,
مس: mesImg,
[LEGACY_GROUP_KATOD]: mesImg,
نقره: noghrehImg,
'سکه پارسیان': parsianImg,
طلا: defaultImg,
آبشده: defaultImg,
}
export function getMetalLabel(metalId: number): string {
switch (metalId) {
case METAL_GOLD:
return 'طلا'
case METAL_SILVER:
return 'نقره'
case METAL_COPPER:
return 'مس'
default:
return 'فلز'
}
}
export function getTotalMetalLabel(metalId: number): string {
return `کل دارایی ${getMetalLabel(metalId)}`
}
export function isSingleMetalCatalog(metalIds: number[]): boolean {
return metalIds.length === 1
}
export function getCatalogMetalIds(products?: Product[] | null): number[] {
const ids = new Set<number>()
for (const product of products ?? []) {
const metalId = Number(product.metal_id)
if (metalId > 0) {
ids.add(metalId)
}
}
return Array.from(ids).sort((a, b) => a - b)
}
export function catalogHasCountBasedProducts(products?: Product[] | null): boolean {
return (products ?? []).some((product) => isCountBasedProduct(product))
}
export function catalogHasMeltedProducts(products?: Product[] | null): boolean {
return (products ?? []).some((product) => isMeltedTradeGroup(product.group_type))
}
export function enrichInventoryCardsWithCatalog<T extends { product_id?: number; file?: ProductFile | null }>(
cards: T[],
catalog: Product[]
): T[] {
return cards.map((card) => {
const fromCatalog = catalog.find((product) => product.id === card.product_id)
if (!fromCatalog) {
return card
}
return {
...card,
file: card.file ?? fromCatalog.file ?? null,
}
})
}
export function enrichInventoryWithCatalog<T extends { id?: number }>(
items: T[],
catalog: Product[]
): T[] {
return items.map((item) => {
const fromCatalog = catalog.find((product) => product.id === item.id)
if (!fromCatalog) {
return item
}
const current = item as T & Product
return {
...fromCatalog,
...current,
wallet: current.wallet ?? fromCatalog.wallet,
file: current.file ?? fromCatalog.file,
metal_id: current.metal_id ?? fromCatalog.metal_id,
group_type: current.group_type ?? fromCatalog.group_type,
}
})
}
export function getProductDisplayImage(product?: {
group_type?: string | null
title?: string | null
file?: ProductFile | null
img?: string | null
} | null): string {
const fileUrl = getFileUrl(product?.file)
if (fileUrl) {
return fileUrl
}
if (product?.img && /^https?:\/\//i.test(product.img)) {
return product.img
}
const group = normalizeProductGroupType(product?.group_type)
if (group && GROUP_DEFAULT_IMAGES[group]) {
return GROUP_DEFAULT_IMAGES[group]
}
return defaultImg
}
type InventoryProduct = ProductUnitSource & {
metal_id?: number | null
title?: string | null
wallet?: { gold?: number | null } | null
}
export function sumCountBasedInventory(products?: InventoryProduct[] | null): number {
return (products ?? [])
.filter((product) => product.title !== 'آبشده نقدی' && isCountBasedProduct(product))
.reduce((sum, product) => sum + Number(product.wallet?.gold ?? 0), 0)
}
export function sumProductWalletByMetal(
products: InventoryProduct[] | null | undefined,
metalId: number
): number {
return (products ?? [])
.filter((product) => Number(product.metal_id) === metalId)
.reduce((sum, product) => sum + Number(product.wallet?.gold ?? 0), 0)
}
export function getMainWalletLine(wallets?: UserWalletLine[] | null): UserWalletLine | undefined {
return wallets?.find((line) => line.product_id == null)
}
export function getMainWalletGold(wallets?: UserWalletLine[] | null): number {
return Number(getMainWalletLine(wallets)?.gold ?? 0)
}
export function getMainWalletCash(wallets?: UserWalletLine[] | null): number {
return Number(getMainWalletLine(wallets)?.cash ?? 0)
}
export function sumWalletsGold(
wallets?: UserWalletLine[] | null,
metalId?: number | null
): number {
if (!wallets?.length) {
return 0
}
return wallets.reduce((sum, line) => {
const weight = Number(line.gold ?? 0)
if (metalId == null) {
return sum + weight
}
if (line.product_id == null) {
return metalId === METAL_GOLD ? sum + weight : sum
}
return Number(line.product?.metal_id) === metalId ? sum + weight : sum
}, 0)
}
export function sumProductWalletsGold(
wallets?: UserWalletLine[] | null,
metalId?: number | null
): number {
return (wallets ?? [])
.filter((line) => line.product_id != null)
.reduce((sum, line) => {
const weight = Number(line.gold ?? 0)
if (metalId == null) {
return sum + weight
}
return Number(line.product?.metal_id) === metalId ? sum + weight : sum
}, 0)
}
export function sumInventoryMetalWeight(products?: InventoryProduct[] | null): number {
return (products ?? [])
.filter((product) => product.title !== 'آبشده نقدی')
.reduce((sum, product) => sum + Number(product.wallet?.gold ?? 0), 0)
}
export function getTotalMetalWeight(
walletInfo?: Record<string, unknown> | null,
wallets?: UserWalletLine[] | null,
inventoryProducts?: InventoryProduct[] | null
): number {
const fromInventory = sumInventoryMetalWeight(inventoryProducts)
if (fromInventory > 0) {
return fromInventory
}
const fromProductWallets = sumProductWalletsGold(wallets)
if (fromProductWallets > 0) {
return fromProductWallets
}
if (wallets?.length) {
return getMainWalletGold(wallets)
}
return Number(walletInfo?.treasure ?? walletInfo?.gold_sum ?? walletInfo?.count_gold ?? 0)
}
/** فقط موجودی نقدی کیف اصلی — فیلد gold (مثل 0.3 کیلوگرم) جزو دارایی ریالی نیست */
export function getRialCashAmount(
walletInfo?: Record<string, unknown> | null,
wallets?: UserWalletLine[] | null
): number {
const mainCash = getMainWalletCash(wallets)
if (mainCash > 0) {
return mainCash
}
return Number(walletInfo?.count_cash ?? walletInfo?.cash ?? 0)
}
export function getTotalRialEquivalent(walletInfo?: Record<string, unknown> | null): number {
return Number(walletInfo?.count_cash_total ?? 0)
}
export function getMetalAssetAmount(
walletInfo: Record<string, unknown> | null | undefined,
metalId: number,
inventoryProducts?: InventoryProduct[] | null
): number {
if (inventoryProducts?.length) {
const fromProducts = sumProductWalletByMetal(inventoryProducts, metalId)
if (fromProducts > 0 || inventoryProducts.some((product) => Number(product.metal_id) === metalId)) {
return fromProducts
}
}
if (!walletInfo) {
return 0
}
switch (metalId) {
case METAL_GOLD:
return Number(walletInfo.count_gold_wallets ?? walletInfo.count_gold ?? 0)
case METAL_SILVER:
return Number(walletInfo.count_silver ?? 0)
case METAL_COPPER:
return Number(walletInfo.count_copper ?? 0)
default:
return 0
}
}
export function getMetalAssetAmountForDisplay(
walletInfo: Record<string, unknown> | null | undefined,
metalId: number,
catalogMetalIds: number[],
inventoryProducts?: InventoryProduct[] | null,
wallets?: UserWalletLine[] | null
): number {
if (isSingleMetalCatalog(catalogMetalIds)) {
return getTotalMetalWeight(walletInfo, wallets, inventoryProducts)
}
const productWeight = sumProductWalletByMetal(inventoryProducts, metalId)
const mainWalletWeight = wallets?.length
? getMainWalletGold(wallets)
: Number(walletInfo?.count_gold_wallet ?? 0)
if (catalogHasMeltedProducts(inventoryProducts as Product[] | null | undefined) && metalId === catalogMetalIds[0]) {
return productWeight + mainWalletWeight
}
if (wallets?.length) {
const walletWeight = sumWalletsGold(wallets, metalId)
if (walletWeight > 0) {
return walletWeight
}
}
return productWeight || getMetalAssetAmount(walletInfo, metalId, inventoryProducts)
}
+75
View File
@@ -0,0 +1,75 @@
/** دسته‌بندی یکسان محصول در همه اپ‌های ماژولار */
export const PRODUCT_CATEGORY_ABSHODE = 'آبشده'
export const UNIFIED_PRODUCT_CATEGORIES = [
PRODUCT_CATEGORY_ABSHODE,
'مکعب',
'گوی',
'سکه',
'سکه پارسیان',
'مس',
'نقره',
] as const
/** دسته‌های قدیمی بورس مس — سازگاری با داده موجود */
export const LEGACY_GROUP_KATOD = 'کاتد مس'
export const LEGACY_GROUP_MAFTOL = 'مفتول مس'
export const LEGACY_GROUP_GOLD = 'طلا'
/** دسته‌های قدیمی که UI آبشده‌ای دارند — «طلا» عمداً نیست (گاروسی با DealProduct می‌ماند) */
export const LEGACY_MELTED_GROUP_TYPES = [LEGACY_GROUP_KATOD] as const
export function normalizeProductGroupType(groupType?: string | null) {
return (groupType ?? '').trim()
}
/** محصول آبشده‌ای — UI گرم/کیلوگرم مثل indexGold */
export function isMeltedTradeGroup(groupType?: string | null) {
const group = normalizeProductGroupType(groupType)
return group === PRODUCT_CATEGORY_ABSHODE || LEGACY_MELTED_GROUP_TYPES.includes(group as typeof LEGACY_MELTED_GROUP_TYPES[number])
}
export function isMetalCommodityGroup(groupType?: string | null) {
const group = normalizeProductGroupType(groupType)
return group === 'مس' || group === 'نقره'
}
export function isLegacyMaftolGroup(groupType?: string | null) {
return normalizeProductGroupType(groupType) === LEGACY_GROUP_MAFTOL
}
/** نگاشت دسته قدیمی به دسته یکسان */
export function normalizeToUnifiedCategory(groupType?: string | null) {
const group = normalizeProductGroupType(groupType)
if (group === LEGACY_GROUP_KATOD || group === LEGACY_GROUP_GOLD) {
return PRODUCT_CATEGORY_ABSHODE
}
if (group === LEGACY_GROUP_MAFTOL) {
return 'مس'
}
return group
}
export type MeltedPriceSource = 'app' | 'fixed' | 'reference'
export function resolveMeltedPriceSource(product?: {
reading_method?: string | null
direct_price?: number | null
} | null): MeltedPriceSource {
if (product?.reading_method) {
return 'reference'
}
if (Number(product?.direct_price) === 1) {
return 'fixed'
}
return 'app'
}
export function isMeltedProductUsingAppPrice(product?: {
group_type?: string | null
reading_method?: string | null
direct_price?: number | null
} | null) {
return isMeltedTradeGroup(product?.group_type)
&& resolveMeltedPriceSource(product) === 'app'
}
+121 -46
View File
@@ -1,18 +1,22 @@
import type { SelectItem } from '@/models/SelectItem'
import { isBoursecuProject } from '@/utils/config'
import { useSettingsStore } from '@/store/settingsStore'
import {
isLegacyMaftolGroup,
isMeltedTradeGroup,
LEGACY_GROUP_KATOD,
LEGACY_GROUP_MAFTOL,
normalizeProductGroupType,
PRODUCT_CATEGORY_ABSHODE,
} from '@/utils/productCategories'
/** شناسه group_type محصول در دیتابیس — نه برچسب نمایشی */
export const BOURSECU_GROUP_MAFTOL = 'مفتول مس'
export const BOURSECU_GROUP_KATOD = 'کاتد مس'
export const BOURSECU_GROUP_ABSHODE = 'آبشده'
/** @deprecated از isMeltedTradeGroup استفاده کنید */
export const BOURSECU_GROUP_ABSHODE = PRODUCT_CATEGORY_ABSHODE
export const BOURSECU_GROUP_KATOD = LEGACY_GROUP_KATOD
export const BOURSECU_GROUP_MAFTOL = LEGACY_GROUP_MAFTOL
export const BOURSECU_WALLET_LABEL_GENERIC = 'موجودی کیف'
export function normalizeProductGroupType(groupType?: string | null) {
return (groupType ?? '').trim()
}
export function isBoursecuDealProductGroup(groupType?: string | null) {
if (!isBoursecuProject()) {
return false
@@ -22,10 +26,12 @@ export function isBoursecuDealProductGroup(groupType?: string | null) {
return group === BOURSECU_GROUP_MAFTOL
|| group === BOURSECU_GROUP_KATOD
|| group === BOURSECU_GROUP_ABSHODE
|| group === 'مس'
}
export function isMaftolMesGroup(groupType?: string | null) {
return normalizeProductGroupType(groupType) === BOURSECU_GROUP_MAFTOL
const group = normalizeProductGroupType(groupType)
return group === BOURSECU_GROUP_MAFTOL || (isBoursecuProject() && group === 'مس')
}
export function isKatodMesGroup(groupType?: string | null) {
@@ -33,7 +39,7 @@ export function isKatodMesGroup(groupType?: string | null) {
}
export function isGoldOnlyDealGroup(groupType?: string | null) {
return normalizeProductGroupType(groupType) === BOURSECU_GROUP_ABSHODE
return isMeltedTradeGroup(groupType)
}
export interface ProductUnitSource {
@@ -43,6 +49,11 @@ export interface ProductUnitSource {
amount?: number | null
}
export function isWeightBasedProductUnit(unit?: string | null) {
const value = (unit ?? '').trim()
return value === 'کیلوگرم' || value === 'گرم'
}
const COUNT_BASED_GROUP_TYPES = ['سکه', 'گوی', 'مکعب', 'شمش', 'سکه پارسیان']
/** مطابق ادمین: وزن «دارد» یعنی amount مقدار واقعی است؛ «ندارد» یعنی amount = 1 */
@@ -52,14 +63,19 @@ export function hasProductUnitWeight(product?: ProductUnitSource | null) {
}
export function getProductWeightUnit(product?: ProductUnitSource | null) {
const unit = product?.unit?.trim()
if (unit && isWeightBasedProductUnit(unit)) {
return unit
}
if (isBoursecuProject()) {
const group = normalizeProductGroupType(product?.group_type)
if (group === BOURSECU_GROUP_MAFTOL || group === BOURSECU_GROUP_KATOD || group === BOURSECU_GROUP_ABSHODE) {
if (group === BOURSECU_GROUP_MAFTOL || group === BOURSECU_GROUP_KATOD || group === BOURSECU_GROUP_ABSHODE || group === 'مس' || isMeltedTradeGroup(group)) {
return getWeightUnit()
}
}
if (!isCountBasedProduct(product) || isGoldOnlyDealGroup(product?.group_type)) {
if (!isCountBasedProduct(product) || isMeltedTradeGroup(product?.group_type)) {
return getWeightUnit()
}
@@ -124,12 +140,16 @@ export function isCountBasedProduct(product?: ProductUnitSource | null) {
return false
}
if (isWeightBasedProductUnit(product.unit)) {
return false
}
if (product.direct_price != null && product.direct_price !== 0) {
return true
}
const group = normalizeProductGroupType(product.group_type)
if (group === BOURSECU_GROUP_MAFTOL || group === BOURSECU_GROUP_KATOD) {
if (group === BOURSECU_GROUP_MAFTOL || isLegacyMaftolGroup(group) || (isBoursecuProject() && group === 'مس')) {
return true
}
@@ -137,15 +157,15 @@ export function isCountBasedProduct(product?: ProductUnitSource | null) {
}
export function getProductQuantityUnit(product?: ProductUnitSource | null) {
if (isCountBasedProduct(product)) {
return 'عدد'
}
const unit = product?.unit?.trim()
if (unit) {
return unit
}
if (isCountBasedProduct(product)) {
return 'عدد'
}
return getWeightUnit()
}
@@ -157,17 +177,34 @@ function getDefaultTypeDealOptions(): SelectItem[] {
]
}
export function getProductDealMethodOptions(groupType?: string | null): SelectItem[] {
export function getProductDealMethodOptions(groupType?: string | null, isBuy = true): SelectItem[] {
const settingsStore = useSettingsStore()
if (!isBoursecuProject()) {
return getDefaultTypeDealOptions()
if (isBuy) {
return [
{ value: 'نقدی', key: 'cash' },
{ value: settingsStore.metalTypeLabel, key: 'gold' },
]
}
return [
{ value: 'نقدی', key: 'cash' },
{ value: `دریافت ${settingsStore.metalTypeLabel}`, key: 'gold' },
]
}
if (isMaftolMesGroup(groupType)) {
if (isBuy) {
return [
{ value: `پرداخت با ${settingsStore.metalTypeLabel}`, key: 'katod' },
{ value: 'نقدی', key: 'cash' },
]
}
return [
{ value: settingsStore.metalTypeLabel, key: 'katod' },
{ value: 'نقدی', key: 'cash' },
{ value: `دریافت ${settingsStore.metalTypeLabel}`, key: 'katod' },
]
}
@@ -175,15 +212,38 @@ export function getProductDealMethodOptions(groupType?: string | null): SelectIt
return [{ value: 'نقدی', key: 'cash' }]
}
if (isGoldOnlyDealGroup(groupType)) {
if (isMeltedTradeGroup(groupType)) {
return [{ value: settingsStore.meltedGoldLabel, key: 'gold' }]
}
return getDefaultTypeDealOptions()
}
export function getDefaultProductDealMethod(groupType?: string | null) {
return getProductDealMethodOptions(groupType)[0]?.key ?? 'cash'
export function getDefaultProductDealMethod(groupType?: string | null, isBuy = true) {
return getProductDealMethodOptions(groupType, isBuy)[0]?.key ?? 'cash'
}
export function getProductDealMethodPlaceholder(isBuy = true) {
return isBuy ? 'نحوه خرید را انتخاب کنید' : 'نحوه دریافت را انتخاب کنید'
}
export function formatMainMetalReceiveText(weight?: number | null) {
return `${useSettingsStore().metalTypeLabel}: ${weight ?? 0}${getWeightUnit()}`
}
export function calcSellReceivedMetalWeight(
count?: number | null,
product?: ProductUnitSource & { percent_fee_sell?: number | null } | null,
) {
const quantity = Number(count ?? 0)
const unitAmount = Number(product?.amount ?? 0)
if (!quantity || !unitAmount) {
return 0
}
const grossAmount = quantity * unitAmount
const feeRate = Number(product?.percent_fee_sell ?? 0)
return grossAmount - feeRate * grossAmount
}
export function isCashLikeDealMethod(method?: string | null) {
@@ -204,36 +264,42 @@ export function getMeltedGoldWalletLabel() {
return `موجودی کیف ${useSettingsStore().meltedGoldLabel}`
}
export function getGoldWalletLabel(groupType?: string | null) {
const settingsStore = useSettingsStore()
export function getBoursecuMetalWalletLabel(groupType?: string | null) {
const group = normalizeProductGroupType(groupType)
if (group === BOURSECU_GROUP_MAFTOL) {
return BOURSECU_GROUP_MAFTOL
}
if (group === BOURSECU_GROUP_KATOD) {
return BOURSECU_GROUP_KATOD
}
if (group === BOURSECU_GROUP_ABSHODE) {
return useSettingsStore().meltedGoldLabel
}
return useSettingsStore().metalTypeLabel
}
export function getGoldWalletLabel(groupType?: string | null) {
if (!isBoursecuProject()) {
return getMainMetalWalletLabel()
}
const group = normalizeProductGroupType(groupType)
if (group === BOURSECU_GROUP_MAFTOL) {
return `موجودی کیف ${BOURSECU_GROUP_MAFTOL}`
if (group === BOURSECU_GROUP_MAFTOL
|| group === BOURSECU_GROUP_KATOD
|| group === BOURSECU_GROUP_ABSHODE) {
return `موجودی کیف ${getBoursecuMetalWalletLabel(groupType)}`
}
if (group === BOURSECU_GROUP_KATOD || group === BOURSECU_GROUP_ABSHODE || !group) {
return group === BOURSECU_GROUP_ABSHODE
? getMeltedGoldWalletLabel()
: getMainMetalWalletLabel()
if (!group) {
return getMainMetalWalletLabel()
}
return BOURSECU_WALLET_LABEL_GENERIC
}
export function getCashWalletLabel(groupType?: string | null) {
if (!isBoursecuProject()) {
return 'موجودی کیف پول'
}
const group = normalizeProductGroupType(groupType)
if (group === BOURSECU_GROUP_MAFTOL) {
return `موجودی کیف ${BOURSECU_GROUP_MAFTOL}`
}
/** پرداخت نقدی همیشه از کیف پول ریالی — مستقل از نوع محصول */
export function getCashWalletLabel(_groupType?: string | null) {
return 'موجودی کیف پول'
}
@@ -250,7 +316,7 @@ export function getMaftolAssetLabel() {
}
export function getWeightUnit() {
return isBoursecuProject() ? 'کیلوگرم' : 'گرم'
return useSettingsStore().tradeWeightUnit
}
export function formatBoursecuAssetAmount(amount?: number | null) {
@@ -269,12 +335,21 @@ export function formatCashWalletBalanceText(cashFormatted: string | number, grou
return `${getCashWalletLabel(groupType)}: ${cashFormatted} ریال`
}
export function getInsufficientGoldWalletMessage(groupType?: string | null) {
return `${getGoldWalletLabel(groupType)} ناکافی است`
/** برچسب کیف فلزی متناسب با نحوه پرداخت (مثلاً کاتد مس برای خرید مفتول با کیف کاتد) */
export function getMetalWalletLabelForDealMethod(method?: string | null, groupType?: string | null) {
if (!isBoursecuProject() || method === 'katod') {
return getMainMetalWalletLabel()
}
return getGoldWalletLabel(groupType)
}
export function getInsufficientCashWalletMessage(groupType?: string | null) {
return `${getCashWalletLabel(groupType)} ناکافی است`
export function getInsufficientGoldWalletMessage(groupType?: string | null, method?: string | null) {
return `${getMetalWalletLabelForDealMethod(method, groupType)} ناکافی است`
}
export function getInsufficientCashWalletMessage(_groupType?: string | null) {
return `${getCashWalletLabel()} ناکافی است`
}
export function getInsufficientMainMetalWalletMessage() {
+30 -6
View File
@@ -1,13 +1,28 @@
import type { Product } from '@/models/products'
import { getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@/utils/price'
import { isMetalCommodityGroup, isMeltedProductUsingAppPrice, isMeltedTradeGroup } from '@/utils/productCategories'
function applyPriceOffsetPercent(basePrice: number, offsetPercent?: number | null) {
const offset = Number(offsetPercent ?? 0)
if (!offset) {
return basePrice
}
return Math.round(basePrice * (1 + offset / 100))
}
/** قیمت خرید نمایشی محصول (همان مقداری که در لیست و اکشن‌شیت نشان داده می‌شود) */
export function getProductBuyPrice(product: Product): number {
if (product.group_type === 'آبشده') {
return getTradeBuyPrice(lastPrice.value) + (product.cash_fee_buy ?? 0)
if (isMeltedProductUsingAppPrice(product)) {
const base = applyPriceOffsetPercent(getTradeBuyPrice(lastPrice.value), product.price_offset_percent)
return base + (product.cash_fee_buy ?? 0)
}
if (['مس', 'نقره'].includes(product.group_type)) {
if (isMeltedTradeGroup(product.group_type)) {
return (product.price ?? 0) + (product.cash_fee_buy ?? 0)
}
if (isMetalCommodityGroup(product.group_type)) {
const base = (product.price_profit ?? 0) + (product.price ?? 0)
return base + (product.cash_fee_buy ?? 0)
}
@@ -18,14 +33,23 @@ export function getProductBuyPrice(product: Product): number {
: basePrice
}
/** قیمت فروش نمایشی آبشده — فقط cash_fee_sell محصول اختلاف ایجاد می‌کند */
/** قیمت فروش نمایشی محصول آبشده‌ای */
export function getProductSellPrice(product: Product): number {
if (product.group_type === 'آبشده') {
return getTradeSellPrice(lastPrice.value) - (product.cash_fee_sell ?? 0)
if (isMeltedProductUsingAppPrice(product)) {
const base = applyPriceOffsetPercent(getTradeSellPrice(lastPrice.value), product.price_offset_percent)
return base - (product.cash_fee_sell ?? 0)
}
if (isMeltedTradeGroup(product.group_type)) {
const base = (product.price_profit ?? product.price ?? 0)
return base - (product.cash_fee_sell ?? 0)
}
return getTradeSellPrice(lastPrice.value)
}
export function isProductPriceInactive(product: Product): boolean {
return getProductBuyPrice(product) <= 0
}
export { isMeltedTradeGroup, isMeltedProductUsingAppPrice } from '@/utils/productCategories'
+33
View File
@@ -0,0 +1,33 @@
export const TRADE_WEIGHT_UNIT_GRAM = 'گرم'
export const TRADE_WEIGHT_UNIT_KILOGRAM = 'کیلوگرم'
export function isKilogramUnit(unit?: string | null) {
const value = (unit ?? '').trim()
return value === TRADE_WEIGHT_UNIT_KILOGRAM || value === 'kilogram' || value === 'kg'
}
/** واحد نمایش از ستینگ — خالی یا نامعتبر = گرم */
export function resolveTradeWeightUnit(settingValue?: string | number | null) {
return isKilogramUnit(settingValue?.toString()) ? TRADE_WEIGHT_UNIT_KILOGRAM : TRADE_WEIGHT_UNIT_GRAM
}
export function weightToGrams(value: number, fromUnit?: string | null) {
return isKilogramUnit(fromUnit) ? value * 1000 : value
}
export function gramsToTradeUnit(grams: number, displayUnit?: string | null) {
return isKilogramUnit(displayUnit ?? resolveTradeWeightUnit(null)) ? grams / 1000 : grams
}
export function convertWeightToDisplayUnit(
value: number,
fromUnit?: string | null,
displayUnit?: string | null
) {
return gramsToTradeUnit(weightToGrams(value, fromUnit), displayUnit)
}
export function formatTradeWeight(value: number, displayUnit?: string | null) {
const unit = resolveTradeWeightUnit(displayUnit)
return `${value} ${unit}`
}
+2 -2
View File
@@ -164,7 +164,7 @@
<div class="flex justify-between mt-3">
<div>مظنه:</div>
<div class="flex items-center">
<div class="font-bold">{{ usePriceWithoutType(((props?.ProductItem?.price_profit) + (props?.ProductItem?.price))) }}</div>
<div class="font-bold">{{ usePriceWithoutType(Math.round(basePriceValue ?? 0)) }}</div>
<div class="text-xs mr-1">ریال</div>
</div>
</div>
@@ -656,6 +656,7 @@ async function ok() {
method: "cash",
number: form.value.goldValue ?? 0
})
confirmAction.value = false
await walletStore.getMyWallet()
await router.push({ name: 'transactions' })
form.value = {
@@ -664,7 +665,6 @@ async function ok() {
percentWallet: undefined,
method: 'cash'
}
// refreshTable()
await fundStore.getMyFund()
message.success('سفارش شما با موفقیت انجام شد')
} catch (e) {
+34 -71
View File
@@ -1,91 +1,54 @@
<template>
<div v-if="item" class="bg-white flex flex-col items-center p-3 rounded-xl">
<!-- <img v-lazy="{ src: itemImg, loading: logo,error: logo}" alt="" class="w-[87px] ">-->
<img v-if="props.item.group_type=='گوی'" :src="goyImg">
<img v-if="props.item.group_type=='مکعب'" :src="mokaabImg">
<img v-if="props.item.group_type=='سکه'" :src="sekkeImg">
<img v-if="props.item.group_type=='مس'" :src="mesImg">
<img v-if="props.item.group_type=='نقره'" :src="noghrehImg">
<!-- <img :src="props.item.img" alt="image">-->
<img v-if="props.item.group_type=='طلا'|| props.item.group_type=='آبشده'|| props.item.group_type== null" :src="defaultImg">
<div class="mt-3">{{props.item?.title?? '-'}}</div>
<img :src="displayImage" class="w-[87px] h-[87px] object-contain" alt="" @error="onImageError">
<div class="mt-3">{{ item.title ?? '-' }}</div>
<div class="mt-1 flex flex-col items-center gap-0.5 text-center">
<div class="flex gap-1">
<div class="font-bold">{{ props.item?.wallet?.gold ?? '-' }}</div>
{{ getProductQuantityUnit(props.item) }}
<div class="font-bold">{{ item.quantity ?? '-' }}</div>
{{ item.unit }}
</div>
<div v-if="getProductUnitWeightLabel(props.item)" class="text-xs text-gray-500">
هر عدد {{ getProductUnitWeightLabel(props.item) }}
<div v-if="item.unit_weight" class="text-xs text-gray-500">
هر عدد {{ item.unit_weight }}
</div>
</div>
<!-- {{props.item?.wallet[0]?.cash}}-->
</div>
</template>
<script setup lang="ts">
import homeImg from '@/assets/img/cash_home.svg'
import giftImg from '@/assets/img/cash_gift.svg'
import circulationImg from '@/assets/img/cash_circulation.svg'
import loveImg from '@/assets/img/cash_love.svg'
import repairsImg from '@/assets/img/cash_repairs.svg'
import savingImg from '@/assets/img/cash_saving.svg'
import {computed} from "vue"
import type {Fund} from "@/models/fund"
import defaultImg from "@/assets/img/defaultAbshodeh.svg"
import goyImg from "@/assets/img/goyImg.svg"
import mokaabImg from "@/assets/img/mokaabImg.svg"
import sekkeImg from "@/assets/img/sekkeImg.svg"
import type { Product } from '@/models/products'
import mesImg from "@/assets/img/mesImg.jpg";
import noghrehImg from "@/assets/img/noghrehImg.webp";
import { getProductQuantityUnit, getProductUnitWeightLabel } from '@/utils/productDealMethod'
/*function itemImg() {
import { computed, ref, watch } from 'vue'
import type { WalletInventoryCard } from '@/models/walletAssets'
import { getProductDisplayImage } from '@/utils/productAssets'
}*/
interface Prop {
item: Product
item: WalletInventoryCard
}
const props = defineProps<Prop>()
const imageSrc = ref('')
const itemImg = computed(() => {
switch (props.item?.title) {
case 'خرید لوازم منزل':
return homeImg
case 'هدیه':
return giftImg
case 'گردش':
return circulationImg
case 'ازدواج':
return loveImg
case 'تعمیرات':
return repairsImg
case 'پس انداز':
return savingImg
default: return savingImg
}
})
const displayImage = computed(() => imageSrc.value || resolveImage())
/*const itemName = computed(() => {
switch (props.type) {
case 'home':
return 'خرید لوازم منزل'
case 'gift':
return 'هدیه'
case 'circulation':
return 'گردش'
case 'love':
return 'ازدواج'
case 'repairs':
return 'تعمیرات'
case 'saving':
return 'پس انداز'
default: return null
}
})*/
watch(
() => props.item,
() => {
imageSrc.value = resolveImage()
},
{ immediate: true, deep: true }
)
function resolveImage() {
return getProductDisplayImage({
title: props.item.title,
group_type: props.item.group_type,
file: props.item.file,
})
}
function onImageError() {
imageSrc.value = getProductDisplayImage({
title: props.item.title,
group_type: props.item.group_type,
file: null,
})
}
</script>
<style scoped>
</style>
+71 -113
View File
@@ -9,158 +9,116 @@
<div class="text-tertiary bg-primary w-screen md:w-full h-[70vh] fixed md:absolute overflow-hidden">
<img :src="img" alt="" class="w-full absolute bottom-0 left-0 opacity-5 pointer-events-none z-0" />
<div class="pt-15 flex flex-col relative z-10">
<div class="text-tertiary font-bold mr-5 z-20">موجودی دارایی ها</div>
<div class="flex mt-4 justify-center mt-2 w-full z-20">
محصولات:
<div class="text-l mr-4 font-bold">{{ walletStore.walletInfo?.count_product ?? 0}}عدد</div>
<div class="text-tertiary font-bold mr-5 z-20">موجودی دارایی ها</div>
<div v-if="meta?.has_count_based_products" class="flex mt-4 justify-center mt-2 w-full z-20">
محصولات:
<div class="text-l mr-4 font-bold">{{ countBasedInventory }} عدد</div>
</div>
<template v-if="meta?.single_metal && primaryMetalTotal">
<div class="flex justify-center mt-2 w-full z-20">
{{ primaryMetalTotal.label }}:
<div class="text-l mr-4 font-bold">{{ formatMetalTotal(primaryMetalTotal) }}</div>
</div>
<div v-if="nameProject === 'goldsun'" class="flex justify-center mt-2 w-full z-20">
دارایی نقره:
<div class="text-l mr-4 font-bold">{{ walletStore.walletInfo?.count_silver ?? 0}}گرم</div>
</div>
<div v-if="nameProject === 'goldsun'" class="flex justify-center mt-2 w-full z-20">
دارایی مس:
<div class="text-l mr-4 font-bold">{{ walletStore.walletInfo?.count_copper ?? 0}}گرم</div>
</div>
<div v-if="isBoursecuProject()" class="flex justify-center mt-2 w-full z-20">
مجموع موجودی:
<div class="text-l mr-4 font-bold">{{ inventory }} عدد</div>
</div>
<div v-if="!isBoursecuProject()" class="flex justify-center mt-2 w-full z-20">
{{ metalAssetLabel }}:
<div class="text-l mr-4 font-bold">{{ walletStore.walletInfo?.count_gold ?? 0 }}{{ getWeightUnit() }}</div>
</div>
<div class="flex justify-center mt-2 w-full z-20">
دارایی ریالی:
<div class="text-l mr-4 font-bold">{{ usePriceWithoutType(walletStore.walletInfo?.count_cash ?? 0) }}ریال</div>
</div>
<div class="flex justify-center mt-2 w-full z-20">
معادل ریالی مجموع دارایی ها:
<div class="text-l mr-4 font-bold">{{ usePriceWithoutType(walletStore.walletInfo?.count_cash_total ?? 0) }}ریال</div>
</template>
<template v-else>
<div
v-for="metal in metalTotals"
:key="`metal-${metal.metal_id}`"
class="flex justify-center mt-2 w-full z-20"
>
{{ metal.label }}:
<div class="text-l mr-4 font-bold">{{ formatMetalTotal(metal) }}</div>
</div>
</template>
<div v-if="meta?.has_count_based_products" class="flex justify-center mt-2 w-full z-20">
مجموع موجودی:
<div class="text-l mr-4 font-bold">{{ countBasedInventory }} عدد</div>
</div>
<div class="flex justify-center mt-2 w-full z-20">
دارایی ریالی:
<div class="text-l mr-4 font-bold">{{ usePriceWithoutType(cashWallet) }}ریال</div>
</div>
<div class="flex justify-center mt-2 w-full z-20">
معادل ریالی مجموع دارایی ها:
<div class="text-l mr-4 font-bold">{{ usePriceWithoutType(totalRialValue) }}ریال</div>
</div>
</div>
</div>
<div class="pt-[20rem] ">
<div class="bg-gray-100 w-screen md:w-full z-20 relative rounded-t-3xl h-[calc(100vh-20rem-70px)] overflow-y-auto pb-15"
style="box-shadow: 0px -2px 4px -2px #0000001A;">
<div v-if="items.length === 0 && !loading" class="w-full h-full flex justify-center items-center">
<div v-if="inventoryCards.length === 0 && !loading" class="w-full h-full flex justify-center items-center">
<div>
<img :src="empty" alt="" class="w-70 ">
<div v-if="nameProject !== 'abaeigold' " class="text-center text-lg">یک گنج جدید بساز!</div>
<div v-if="nameProject !== 'abaeigold'" class="text-center text-lg">یک گنج جدید بساز!</div>
</div>
</div>
<a-spin :spinning="loading">
<div :class="loading? 'h-[40vh]':''" class="grid grid-cols-2 gap-3 p-5">
<Item v-for="item in items.filter(x => x.title !== 'آبشده نقدی')" :item="item"
@click="router.push({name: 'fund_info', params:{id:item.id}})"
<div :class="loading ? 'h-[40vh]' : ''" class="grid grid-cols-2 gap-3 p-5">
<Item
v-for="item in inventoryCards"
:key="item.product_id"
:item="item"
@click="router.push({ name: 'fund_info', params: { id: item.product_id } })"
/>
</div>
</a-spin>
</div>
</div>
<!-- <div class="fixed w-full flex justify-center bottom-23 z-200 md:right-0">
<div class="rounded-3xl bg-[#0A1B37] text-white px-5 py-2" @click="router.push({name: 'fund_add'})">افزودن گنج
</div>
</div>-->
</div>
</template>
<script lang="ts" setup>
import router from "@/router";
import BasicIcon from "@/components/BasicPacks/BasicIcon.vue";
import BasicModal from "@/components/BasicPacks/BasicModal.vue";
import router from '@/router'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import img from '@/assets/img/user_ly1.svg'
import empty from '@/assets/img/cash_empty.svg'
import Item from './components/Item.vue'
import { onMounted, ref, computed } from "vue";
import {loading} from "@/utils";
import type {TableOutput} from "@/models/table";
import type {Fund} from "@/models/fund";
import {useFundUserStore} from "@/store/fundStore";
import { getMe } from '@/api/me'
import type { User } from '@/models/login'
import {usePriceWithoutType} from "../../../utils/usePrice";
import {useWalletStore} from "@/store/walletStore";
import {useConfigStore} from "@/store/configStore";
import { isBoursecuProject } from '@/utils/config'
import { formatBoursecuAssetAmount, getMetalAssetLabel, getWeightUnit } from '@/utils/productDealMethod'
import { onMounted, computed } from 'vue'
import { loading } from '@/utils'
import { usePriceWithoutType } from '@/utils/usePrice'
import { useConfigStore } from '@/store/configStore'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
const nameProject = useConfigStore().config.name
const metalAssetLabel = computed(() => getMetalAssetLabel())
const { assetsSummary, loadWalletAssets } = useWalletAssets()
const items = ref<Fund[]>([])
const tableOutput = ref<TableOutput<Fund> | null>(null)
const fundStore = useFundUserStore()
const walletStore = useWalletStore()
const userInfo = ref<User>()
const weight = ref<number>(0)
const total = ref<number>(0)
const inventory = computed(() =>
items.value
.filter(x => x.title !== 'آبشده نقدی')
.reduce((sum, x) => sum + (x?.wallet?.gold ?? 0), 0)
const meta = computed(() => assetsSummary.value?.meta)
const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? [])
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const primaryMetalTotal = computed(() => metalTotals.value[0])
const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
const totalRialValue = computed(() => assetsSummary.value?.total_rial_value ?? 0)
const countBasedInventory = computed(() =>
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0)
)
onMounted(() => {
initTable()
})
async function initTable() {
onMounted(async () => {
try {
userInfo.value = await getMe()
loading.value = true
tableOutput.value = fundStore.myFunds ?? await fundStore.getMyFund() ?? null
console.log(tableOutput.value)
items.value.push(...tableOutput.value?.rows ?? [])
items.value.forEach(x => {
total.value += ((x?.wallet?.gold) ?? 0) * ((x?.price) ?? 0)
if (x.title !== 'آبشده نقدی' && x.title !== 'سکه')
weight.value += ((x?.wallet?.gold) ?? 0) * ((x?.amount) ?? 0)
})
await loadWalletAssets(true)
} catch (e) {
console.log(e)
} finally {
loading.value = false
}
})
function summaryMetalWeight(metal: WalletMetalTotal) {
if (inventoryCards.value.length > 0) {
return metal.product_weight
}
return metal.total_weight
}
/*watch(()=> router.currentRoute.value.name, () =>{
console.log('salammmmmmmmmmmmmmmmmmmmmmmmmmm')
})*/
/*
const items = [
{
type: 'home',
amount: 2.7
},
{
type: 'gift',
amount: 13.1
},
{
type: 'saving',
amount: 6.4
},
{
type: 'repairs',
amount: 16.6
},
{
type: 'circulation',
amount: 5.4
},
{
type: 'love',
amount: 3.7
},
]
*/
function formatMetalTotal(metal: WalletMetalTotal) {
return `${summaryMetalWeight(metal)}${metal.unit}`
}
</script>
<style scoped>
</style>
</style>
+37 -29
View File
@@ -6,11 +6,11 @@
<div class="flex justify-evenly w-full px-2 h-11 items-center bg-gray-50 relative rounded ">
<div :class="isBuy?'text-tertiary':'text-gray-400'" class="w-full text-center z-2"
@click.stop="setIsBuy(true) ">
خرید {{ meltedGoldLabel }} {{ props?.ProductItem?.title }}
خرید {{ tradeProductLabel }}
</div>
<div :class="!isBuy?'text-tertiary':'text-gray-400'" class="w-full text-center z-2"
@click.stop="setIsBuy(false) ">
فروش {{ meltedGoldLabel }} {{ props?.ProductItem?.title }}
فروش {{ tradeProductLabel }}
</div>
<!-- <div ref="bganim" class="absolute bg-white h-8 w-1/2 rounded-lg " :style="`transform: translateX(${isbuy? '0':'-100%'}); left: ${isbuy? '0':'100%'}`"></div>-->
<div ref="bganim" :style="useStyle()"
@@ -53,9 +53,9 @@
type="price" @onchange="calculateGold" />
</a-form-item>
<a-form-item :rules="[justNumber()]">
<BasicInput v-model:value="form.goldValue" addon-before="گرم" :addon-bg-color="useConfigStore().config.color"
<BasicInput v-model:value="form.goldValue" :addon-before="weightUnit" :addon-bg-color="useConfigStore().config.color"
addon-text-color="white"
place-holder="مقدار طلا"
:place-holder="amountFieldLabel"
size="large" type="text" inputmode="decimal" @onchange="calculateCash" />
</a-form-item>
<div v-if="cashValidationMessage" class="text-red-700 text-xs font-bold mt-2">
@@ -133,7 +133,7 @@
<div class="flex gap-2 items-center">
<div class="">{{ feeInGrams }}</div>
<div>
گرم
{{ weightUnit }}
</div>
</div>
</div>
@@ -157,13 +157,13 @@
<div>وزن:</div>
<div class="flex items-center">
<div class="font-bold">{{ form.goldValue }}</div>
<div class="text-xs mr-1">گرم</div>
<div class="text-xs mr-1">{{ weightUnit }}</div>
</div>
</div>
<div class="flex justify-between mt-3">
<div>مظنه:</div>
<div class="flex items-center">
<div class="font-bold">{{ usePriceWithoutType(isBuy ? getTradeBuyPrice(lastPrice) : getTradeSellPrice(lastPrice)) }}</div>
<div class="font-bold">{{ usePriceWithoutType(Math.round(goldPriceValue)) }}</div>
<div class="text-xs mr-1">ریال</div>
</div>
</div>
@@ -171,7 +171,7 @@
<div>کارمزد:</div>
<div class="flex items-center gap-2">
<div class="font-bold text-xl">{{ feeInGrams }}</div>
<div class="text-xs mr-1">گرم</div>
<div class="text-xs mr-1">{{ weightUnit }}</div>
</div>
</div>
<div >(معادل {{ equivalentPrice }} ریال)</div>
@@ -236,7 +236,8 @@ import type { Product } from '@/models/products'
import { useFundUserStore } from '@/store/fundStore'
import {useConfigStore} from "@/store/configStore";
import { calcFeeInGrams, loadServiceFeeFromSettings } from '@/utils/serviceFee'
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
import { formatCashWalletBalanceText, formatGoldWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
import { isMeltedTradeGroup } from '@/utils/productCategories'
import { useSettingsStore } from '@/store/settingsStore'
import { storeToRefs } from 'pinia'
import {
@@ -250,6 +251,7 @@ const walletStore = useWalletStore()
const userStore = useUserStore()
const settingsStore = useSettingsStore()
const { meltedGoldLabel } = storeToRefs(settingsStore)
const weightUnit = computed(() => getWeightUnit())
const fundStore = useFundUserStore()
const confirmAction = ref<boolean>(false)
const noCompleteVisible = ref<boolean>(false)
@@ -267,6 +269,12 @@ interface Prop {
const props = withDefaults(defineProps<Prop>(), {})
const isBuy = ref<boolean>(true)
const tradeProductLabel = computed(() => {
const title = props.ProductItem?.title?.trim()
return title || meltedGoldLabel.value
})
const amountFieldLabel = computed(() => `مقدار ${tradeProductLabel.value}`)
const buyPagination = ref<TableEngineInput>({
filters: [{
field: 'type',
@@ -288,8 +296,8 @@ const sellPagination = ref<TableEngineInput>({
const unitPrice = computed(() => {
const product = props.ProductItem
if (product?.group_type === 'آبشده') {
return isBuy.value ? getProductBuyPrice(product) : getProductSellPrice(product)
if (isMeltedTradeGroup(product?.group_type)) {
return isBuy.value ? getProductBuyPrice(product!) : getProductSellPrice(product!)
}
return isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value)
})
@@ -307,6 +315,11 @@ const cashValidationMessage = computed(() =>
productCashValidationMessage(props.ProductItem, form.value?.goldCash, isBuy.value, usePriceWithoutType)
)
const priceUnavailable = computed(() => {
const unit = unitPrice.value
return !unit || Number.isNaN(unit) || unit <= 0
})
const disableTransaction = computed(() =>
loading.value ||
form.value?.goldValue === undefined ||
@@ -321,8 +334,7 @@ const disableTransaction = computed(() =>
(maxOrderCash.value != null && (form.value?.goldCash ?? 0) > maxOrderCash.value) ||
cashValidationMessage.value !== '' ||
(!isBuy.value && form.value.goldValue > walletStore?.walletInfo?.gold) ||
!lastPrice.value ||
(isBuy.value ? getTradeBuyPrice(lastPrice.value) <= 0 : getTradeSellPrice(lastPrice.value) <= 0))
priceUnavailable.value)
function refreshTable() {
sellItems.value = []
@@ -498,7 +510,8 @@ const limitedPrice = computed(() => {
})
function syncFormWithLatestPrice() {
if (!lastPrice.value) return
const unit = unitPrice.value
if (!unit || Number.isNaN(unit)) return
const goldValue = form.value.goldValue
if (goldValue !== undefined && goldValue !== null && goldValue !== '' && !isNaN(Number(goldValue))) {
@@ -513,7 +526,7 @@ function syncFormWithLatestPrice() {
}
watch(
() => [getTradeBuyPrice(lastPrice.value), getTradeSellPrice(lastPrice.value), isBuy.value],
() => [unitPrice.value, isBuy.value, props.ProductItem?.id],
() => {
syncFormWithLatestPrice()
}
@@ -521,20 +534,20 @@ watch(
function calculateCash(val: number) {
priceErrorVisible.value = false
if (!lastPrice.value) return
const unit = unitPrice.value
if (!unit || Number.isNaN(unit)) return
const unit = isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value)
form.value.goldCash = val ? parseFloat((val * unit).toFixed(0)) : undefined
}
function calculateGold(val: number) {
if (!lastPrice.value) return
const unit = unitPrice.value
if (!unit || Number.isNaN(unit)) return
const unit = isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value)
if (isBuy.value) {
if (val) {
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit)))
priceErrorVisible.value = parseInt(finalPrice.value) > 0
priceErrorVisible.value = parseInt(String(finalPrice.value)) > 0
} else if (val.toString() === '') {
form.value.goldValue = undefined
priceErrorVisible.value = false
@@ -544,7 +557,7 @@ function calculateGold(val: number) {
}
} else if (val) {
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit)))
priceErrorVisible.value = parseInt(finalPrice.value) > 0
priceErrorVisible.value = parseInt(String(finalPrice.value)) > 0
} else if (val.toString() === '') {
form.value.goldValue = undefined
priceErrorVisible.value = false
@@ -590,12 +603,7 @@ const formatter = (value: number) => {
const price = computed((): Price => <Price>lastPrice.value ?? 0)
const goldPriceValue = computed(() => {
if (!lastPrice.value?.price) return 0
return isBuy.value
? getTradeBuyPrice(lastPrice.value)
: getTradeSellPrice(lastPrice.value)
})
const goldPriceValue = computed(() => unitPrice.value)
async function initPrice() {
try {
@@ -625,10 +633,11 @@ async function ok() {
infoVisible.value = true
await createOrder({
direction: isBuy.value ? 1 : 2,
price: isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value),
price: Math.round(unitPrice.value),
amount: form.value.goldValue ?? 0,
abshode_id: props.ProductItem?.id,
})
confirmAction.value = false
await walletStore.getMyWallet()
await router.push({ name: 'transactions' })
form.value = {
@@ -636,7 +645,6 @@ async function ok() {
goldCash: undefined,
percentWallet: undefined
}
// refreshTable()
message.success('سفارش شما با موفقیت انجام شد')
await fundStore.getMyFund()
} catch (e) {
@@ -1,36 +1,82 @@
<template>
<div class="bg-primary rounded-lg p-2 py-3 mt-2">
<div class="flex justify-center text-tertiary w-full z-20">
<div v-if="meta?.has_count_based_products" class="flex justify-center text-tertiary w-full z-20">
محصولات:
<div class="text-l mr-2 font-bold">{{ userStore?.userInfo?.wallet?.count_product ?? 0 }} عدد</div>
</div>
<div v-if="!isBoursecuProject()" class="flex mt-2 justify-center text-tertiary w-full z-20">
{{ metalAssetLabel }}:
<div class="text-l mr-2 font-bold">{{ (userStore?.userInfo?.wallet?.count_gold ?? 0).toFixed(3) }} {{ weightUnit }}</div>
<BasicIcon @click="$emit('openGoldModal')" icon="vuesax-linear:info-circle" size="18" color="tertiary" />
<div class="text-l mr-2 font-bold">{{ countBasedInventory }} عدد</div>
</div>
<template v-if="meta?.single_metal && primaryMetalTotal">
<div class="flex mt-2 justify-center text-tertiary w-full z-20">
{{ primaryMetalTotal.label }}:
<div class="text-l mr-2 font-bold">{{ formatMetalTotal(primaryMetalTotal) }}</div>
<BasicIcon
icon="vuesax-linear:info-circle"
size="18"
color="tertiary"
@click="$emit('openGoldModal')"
/>
</div>
</template>
<template v-else>
<div
v-for="metal in metalTotals"
:key="metal.metal_id"
class="flex mt-2 justify-center text-tertiary w-full z-20"
>
{{ metal.label }}:
<div class="text-l mr-2 font-bold">{{ formatMetalTotal(metal) }}</div>
<BasicIcon
v-if="metal.metal_id === metalTotals[0]?.metal_id"
icon="vuesax-linear:info-circle"
size="18"
color="tertiary"
@click="$emit('openGoldModal')"
/>
</div>
</template>
<div class="flex mt-2 justify-center text-tertiary w-full z-20">
دارایی ریالی:
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(userStore?.userInfo?.wallet?.count_cash ?? 0) }} ریال</div>
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(cashWallet) }} ریال</div>
<BasicIcon @click="$emit('openRialModal')" icon="vuesax-linear:info-circle" size="18" color="tertiary" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useUserStore } from '@/store/userStore'
import { computed, onMounted } from 'vue'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import {usePriceWithoutType} from "../../../../utils/usePrice";
import { isBoursecuProject } from '@/utils/config'
import { getMetalAssetLabel, getWeightUnit } from '@/utils/productDealMethod'
import { usePriceWithoutType } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
const userStore = useUserStore()
const metalAssetLabel = computed(() => getMetalAssetLabel())
const weightUnit = computed(() => getWeightUnit())
const { assetsSummary, loadWalletAssets } = useWalletAssets()
defineEmits<{
openGoldModal: []
openRialModal: []
}>()
</script>
const meta = computed(() => assetsSummary.value?.meta)
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const primaryMetalTotal = computed(() => metalTotals.value[0])
const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? [])
const countBasedInventory = computed(() =>
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0)
)
onMounted(() => {
void loadWalletAssets()
})
function summaryMetalWeight(metal: WalletMetalTotal) {
if (inventoryCards.value.length > 0) {
return metal.product_weight
}
return metal.total_weight
}
function formatMetalTotal(metal: WalletMetalTotal) {
return `${summaryMetalWeight(metal)}${metal.unit}`
}
</script>
+44 -50
View File
@@ -5,50 +5,27 @@
<div class="w-full text-center font-bold">موجودی ها</div>
<div class="h-30vh overflow-y-auto">
<div class="mt-5">
<BasicInfoItem
<template v-for="metal in metalTotals" :key="metal.metal_id">
<BasicInfoItem
class="flex justify-between"
:title="`مجموعه کل دارایی ${settingsStore.metalTypeLabel}`"
:title="metal.label"
is-line
:info="`در این قسمت مجموع کل وزن ${settingsStore.metalTypeLabel} آبشده (${(walletInfo?.gold ?? 0)?.toFixed(3)}) + ارزش دارایی ها (${(walletInfo?.treasure_sum ?? 0)?.toFixed(3)} ) را مشاهده میفرمایید.`"
:infoHead="`مجموع کل دارایی ${settingsStore.metalTypeLabel}`"
:value="parseFloat((walletInfo?.gold_sum ?? 0).toFixed(2)) + ' ' + weightUnit"
:value="formatMetalTotal(metal)"
/>
<a-divider class="!my-1" />
</template>
<BasicInfoItem
class="flex justify-between"
title="دارایی کیف پول ریالی"
is-line
:value="usePrice(cashWallet)"
/>
<a-divider class="!my-1" />
<BasicInfoItem
class="flex justify-between"
title="دارایی کیف پول ریالی"
is-line
:value="usePrice(walletInfo?.cash ?? 0)"
/>
<a-divider class="!my-1" />
<BasicInfoItem
class="flex justify-between"
:title="`دارایی کیف پول ${settingsStore.metalTypeLabel}`"
is-line
:value="(walletInfo?.count_gold_wallet ?? 0) + ' ' + weightUnit"
/>
<a-divider v-if="nameProject === 'goldsun'" class="!my-1" />
<BasicInfoItem
v-if="nameProject === 'goldsun'"
class="flex justify-between"
title="دارایی کیف پول نقره"
is-line
:value="(walletInfo?.count_silver ?? 0) + ' گرم'"
/>
<a-divider v-if="nameProject === 'goldsun'" class="!my-1" />
<BasicInfoItem
v-if="nameProject === 'goldsun'"
class="flex justify-between"
title="دارایی کیف پول مس"
is-line
:value="(walletInfo?.count_copper ?? 0) + ' گرم'"
/>
<a-divider class="!my-1" />
<BasicInfoItem
class="flex justify-between"
title="معادل ریالی مجموع دارایی ها"
is-line
:value="usePrice(walletInfo?.count_cash_total ?? 0)"
class="flex justify-between"
title="معادل ریالی مجموع دارایی ها"
is-line
:value="usePrice(totalRialValue)"
/>
</div>
</div>
@@ -58,13 +35,12 @@
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { computed, onMounted, watch } from 'vue'
import BasicActionSheet from '@/components/BasicPacks/BasicActionSheet.vue'
import BasicInfoItem from '@/components/BasicPacks/BasicInfoItem.vue'
import { useConfigStore } from '@/store/configStore'
import { useSettingsStore } from '@/store/settingsStore'
import { getWeightUnit } from '@/utils/productDealMethod'
import {usePrice} from "@/utils/usePrice";
import { usePrice } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
const props = defineProps<{
show: boolean
@@ -76,13 +52,31 @@ const emit = defineEmits<{
'update:show': [value: boolean]
}>()
const config = useConfigStore()
const nameProject = config.config.name
const settingsStore = useSettingsStore()
const weightUnit = computed(() => getWeightUnit())
const { assetsSummary, loadWalletAssets } = useWalletAssets()
const visible = computed({
get: () => props.show,
set: (val) => emit('update:show', val)
set: (val) => emit('update:show', val),
})
</script>
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
const totalRialValue = computed(() => assetsSummary.value?.total_rial_value ?? 0)
onMounted(() => {
void loadWalletAssets()
})
watch(
() => props.show,
(open) => {
if (open) {
void loadWalletAssets(true)
}
}
)
function formatMetalTotal(metal: WalletMetalTotal) {
return `${metal.total_weight} ${metal.unit}`
}
</script>
+2
View File
@@ -82,6 +82,7 @@ import {useWindowScroll} from '@vueuse/core'
import {loading, removeToken} from '@/utils'
import {useUserStore} from '@/store/userStore'
import {useWalletStore} from '@/store/walletStore'
import { useWalletAssets } from '@/composables/useWalletAssets'
import {useConfigStore} from '@/store/configStore'
import {useFundUserStore} from '@/store/fundStore'
import {usePrice, usePriceWithoutType} from '../../../utils/usePrice'
@@ -204,6 +205,7 @@ function copyCode() {
async function logout() {
userStore.userInfo = undefined
walletStore.walletInfo = undefined
useWalletAssets().clearWalletAssets()
removeToken()
await router.push({name: 'login'})
window.location.reload()
@@ -54,7 +54,7 @@
:show-search="false"
value-name="value"
:allow-clear="false"
:placeholder="isBuy?'نحوه خرید را انتخاب کنید':' نحوه فروش را انتخاب کنید'"
:placeholder="getProductDealMethodPlaceholder(isBuy)"
size="large"
:has-tooltip="false" />
</a-form-item>
@@ -103,7 +103,9 @@
<div v-else-if="isBuy && form.method === 'cash'" class="font-bold text-xs">
{{ cashWalletBalanceText }}
</div>
<div class="font-bold text-xs" v-else>{{ `موجودی محصول: ${getInventoryById(props?.ProductItem?.id)} ${getProductQuantityUnit(props?.ProductItem)}` }}
<div class="font-bold text-xs" v-else>
<div>{{ `موجودی محصول: ${getInventoryById(props?.ProductItem?.id)} ${getProductQuantityUnit(props?.ProductItem)}` }}</div>
<div v-if="isMetalReceiveDeal" class="mt-1">{{ sellMetalWalletBalanceText }}</div>
</div>
</Transition>
<Transition mode="out-in" name="fade">
@@ -225,10 +227,15 @@
</div>
<div class="flex justify-between mt-3">
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : 'مبلغ دریافتی:' }}</div>
<div>{{ isBuy ? 'قیمت قابل پرداخت:' : (isMetalReceiveDeal ? 'دریافت:' : 'مبلغ دریافتی:') }}</div>
<div class="flex items-center">
<div>{{ usePriceWithoutType(form.goldCash ?? 0) }}</div>
<div class="text-xs mr-1">ریال</div>
<template v-if="!isBuy && isMetalReceiveDeal">
<div>{{ sellReceivedMetalText }}</div>
</template>
<template v-else>
<div>{{ usePriceWithoutType(form.goldCash ?? 0) }}</div>
<div class="text-xs mr-1">ریال</div>
</template>
</div>
</div>
@@ -269,9 +276,13 @@ import { useFundUserStore } from '@/store/fundStore'
import {
getDefaultProductDealMethod,
getProductDealMethodOptions,
getProductDealMethodPlaceholder,
formatCashWalletBalanceText,
formatGoldWalletBalanceText,
formatMainMetalWalletBalanceText,
formatMainMetalReceiveText,
calcSellReceivedMetalWeight,
isMainMetalWalletDealMethod,
formatProductWeightAmount,
getProductQuantityUnit,
getProductTotalWeightLabel,
@@ -286,7 +297,17 @@ import {
productMinOrderCash
} from '@/utils/productOrderLimit'
const typeDeal = computed(() => getProductDealMethodOptions(props?.ProductItem?.group_type))
const typeDeal = computed(() => getProductDealMethodOptions(props?.ProductItem?.group_type, isBuy.value))
const isMetalReceiveDeal = computed(() =>
!isBuy.value && isMainMetalWalletDealMethod(form.value.method)
)
const sellReceivedMetalText = computed(() =>
formatMainMetalReceiveText(
calcSellReceivedMetalWeight(form.value.goldValue, props?.ProductItem)
)
)
const productGroupType = computed(() => props?.ProductItem?.group_type)
const isCountBasedProductItem = computed(() => isCountBasedProduct(props?.ProductItem))
@@ -314,6 +335,10 @@ const buyMetalWalletBalanceText = computed(() =>
: goldWalletBalanceText.value
)
const sellMetalWalletBalanceText = computed(() =>
formatMainMetalWalletBalanceText(walletStore?.walletInfo?.gold ?? 0)
)
const cashWalletBalanceText = computed(() =>
formatCashWalletBalanceText(
usePriceWithoutType(walletStore?.walletInfo?.cash ?? 0),
@@ -339,6 +364,7 @@ interface Prop {
}
const props = withDefaults(defineProps<Prop>(), {})
const emit = defineEmits<{ ordered: [] }>()
const isBuy = ref<boolean>(true)
const buyTotalPrice = computed(() => {
const item = props?.ProductItem
@@ -520,7 +546,7 @@ const form = ref<Gold>({
})
function resetDealMethod() {
form.value.method = getDefaultProductDealMethod(props?.ProductItem?.group_type)
form.value.method = getDefaultProductDealMethod(props?.ProductItem?.group_type, isBuy.value)
}
watch(
@@ -772,20 +798,21 @@ async function ok() {
method: form.value.method,
number: form.value.goldValue ?? 0
})
confirmAction.value = false
emit('ordered')
await userStore.getMyInfo()
await walletStore.getMyWallet()
await fundStore.getMyFund()
message.success('سفارش شما با موفقیت انجام شد')
await router.push({ name: 'transactions' })
form.value = {
goldValue: undefined,
goldCash: undefined,
percentWallet: undefined,
method: getDefaultProductDealMethod(props?.ProductItem?.group_type)
method: getDefaultProductDealMethod(props?.ProductItem?.group_type, isBuy.value)
}
// refreshTable()
await fundStore.getMyFund()
message.success('سفارش شما با موفقیت انجام شد')
} catch (e) {
// console.log(e)
// await initPrice()
} finally {
loading.value = false
infoVisible.value = false
@@ -11,7 +11,7 @@
<!-- <div v-if="props.ProductItem.group_type!='آبشده'" class="text-secondary font-500">{{ props.ProductItem.amount }}گرم</div>-->
<!-- <div v-else class="text-secondary font-500">حداقل خرید یک گرم</div>-->
<!-- <div>{{usePrice((props.ProductItem.price ?? 0) + (props.ProductItem.cash_fee_buy ?? 0))}}</div>-->
<div v-if="props.ProductItem.group_type=='آبشده'">{{usePrice(goldPriceValue)}}</div>
<div v-if="isMeltedTradeGroup(props.ProductItem.group_type)">{{usePrice(goldPriceValue)}}</div>
<div v-else>{{usePrice(price)}}</div>
<!-- <div v-if="props.ProductItem.group_type!='آبشده'" class="text-xs text-gray-400">شامل 33 هزار تومان اجرت</div>-->
<!-- <div v-else class="text-xs text-gray-400">محاسبه بر اساس قیمت روز</div>-->
@@ -33,6 +33,7 @@ import {usePrice} from '@/utils/usePrice';
import {getFileUrl} from '@/utils/file';
import {computed, ref} from "vue";
import { getProductBuyPrice } from '@/utils/productPrice'
import { isMeltedTradeGroup } from '@/utils/productCategories'
interface Prop {
ProductItem: Product
@@ -58,6 +59,8 @@ const defaultImages: Record<string, string> = {
'مس': mesImg,
'نقره': noghrehImg,
'سکه پارسیان': parsianImg,
'کاتد مس': defaultImg,
'طلا': defaultImg,
}
const displayImage = computed(() => {
@@ -111,7 +114,7 @@ const goldPriceValue = computed(() => getProductBuyPrice(props.ProductItem))
<div class="m-1 flex flex-col gap-1 justify-center">
<div class="text-base font-500">{{ props.ProductItem.title }}</div>
<br>
<div v-if="props.ProductItem.group_type=='آبشده'">{{usePrice(goldPriceValue)}}</div>
<div v-if="isMeltedTradeGroup(props.ProductItem.group_type)">{{usePrice(goldPriceValue)}}</div>
<div v-else>{{usePrice(price)}}</div>
</div>
</div>
+17 -5
View File
@@ -30,16 +30,16 @@
<!-- </BasicActionSheet>-->
<BasicActionSheet placement="bottom" v-model:show="showFilter">
<div class="">
<indexGold v-if="['آبشده'].includes(selectedProduct?.group_type) && !isBoursecuProject()"
<div v-if="showFilter" :key="orderSheetKey">
<indexGold v-if="isMeltedTradeGroup(selectedProduct?.group_type)"
:ProductItem="selectedProduct"
>
</indexGold>
<CopperSilver v-else-if="['مس','نقره'].includes(selectedProduct?.group_type) && !isBoursecuDealProductGroup(selectedProduct?.group_type)"
<CopperSilver v-else-if="isMetalCommodityGroup(selectedProduct?.group_type) && !isBoursecuDealProductGroup(selectedProduct?.group_type)"
:ProductItem="selectedProduct"
>
</CopperSilver>
<DealProduct v-else :ProductItem="selectedProduct"></DealProduct>
<DealProduct v-else :ProductItem="selectedProduct" @ordered="onProductOrdered"></DealProduct>
</div>
</BasicActionSheet>
@@ -105,12 +105,13 @@ import { cloneDeep } from 'lodash'
import img from "@/assets/img/user_ly1.svg";
import BasicModal from "@/components/BasicPacks/BasicModal.vue";
import { isProductPriceInactive } from '@/utils/productPrice'
import { isBoursecuProject } from '@/utils/config'
import { isMetalCommodityGroup, isMeltedTradeGroup } from '@/utils/productCategories'
import { isBoursecuDealProductGroup } from '@/utils/productDealMethod'
import { loadServiceFeeFromSettings } from '@/utils/serviceFee'
const activekey = ref('طلا' ||'آبشده')
const showFilter = ref(false)
const orderSheetKey = ref(0)
const selectedProduct = ref<Product>()
const closeTime = ref<string>('')
const openTime = ref<string>('')
@@ -137,10 +138,21 @@ function clickProduct(item?: Product) {
return
}
orderSheetKey.value += 1
selectedProduct.value = cloneDeep(item)
showFilter.value = true
}
function onProductOrdered() {
showFilter.value = false
}
watch(showFilter, (open) => {
if (!open) {
orderSheetKey.value += 1
}
})
function changeTab() {
if (activekey.value != 'همه') {
items.value = firstItems.value?.filter((val) =>
+186 -157
View File
@@ -71,7 +71,7 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz"
integrity sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.1", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.22.10", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0":
"@babel/core@^7.11.1", "@babel/core@^7.22.10":
version "7.22.10"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz"
integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==
@@ -291,7 +291,7 @@
"@babel/template" "^7.27.1"
"@babel/types" "^7.27.1"
"@babel/parser@^7.15.8", "@babel/parser@^7.20.15", "@babel/parser@^7.21.3", "@babel/parser@^7.22.10", "@babel/parser@^7.25.3", "@babel/parser@^7.26.5", "@babel/parser@^7.27.2":
"@babel/parser@^7.20.15", "@babel/parser@^7.21.3", "@babel/parser@^7.22.10", "@babel/parser@^7.25.3", "@babel/parser@^7.26.5", "@babel/parser@^7.27.2":
version "7.27.2"
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz"
integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==
@@ -1006,11 +1006,116 @@
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz"
integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
"@esbuild/android-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
"@esbuild/android-arm@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
"@esbuild/android-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
"@esbuild/darwin-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
"@esbuild/darwin-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
"@esbuild/freebsd-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
"@esbuild/freebsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
"@esbuild/linux-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
"@esbuild/linux-arm@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
"@esbuild/linux-ia32@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
"@esbuild/linux-loong64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
"@esbuild/linux-mips64el@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
"@esbuild/linux-ppc64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
"@esbuild/linux-riscv64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
"@esbuild/linux-s390x@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
"@esbuild/linux-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz"
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
"@esbuild/netbsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
"@esbuild/openbsd-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
"@esbuild/sunos-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
"@esbuild/win32-arm64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
"@esbuild/win32-ia32@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
"@esbuild/win32-x64@0.18.20":
version "0.18.20"
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d"
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz"
@@ -1139,7 +1244,7 @@
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5"
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@@ -1243,16 +1348,16 @@
resolved "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.0.tgz"
integrity sha512-yhxwIlFVSVcMym3O31HoMnRXpoenmpIxcj4Yoes2DUpe+xCJnA7ECQP1Vw889V0jTt/2nzvpLQ/UuMYCd3JPIg==
"@types/estree@^1.0.0":
version "1.0.1"
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz"
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/estree@^1.0.0":
version "1.0.1"
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz"
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
"@types/json-schema@^7.0.9":
version "7.0.12"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz"
@@ -1263,7 +1368,7 @@
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz"
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
"@types/node@*", "@types/node@^18.17.0", "@types/node@>= 14":
"@types/node@*", "@types/node@^18.17.0":
version "18.17.5"
resolved "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz"
integrity sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==
@@ -1306,7 +1411,7 @@
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.59.1":
"@typescript-eslint/parser@^5.59.1":
version "5.62.0"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz"
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
@@ -1592,7 +1697,7 @@
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.1.tgz"
integrity sha512-tUBEtWcF7wFtII7ayNiLNDTCE1X1afySEo+XNVMNkFXaThENyCowIEX095QqbJZGTgoOcSVDJGlnde2NG4jtbQ==
"@volar/language-core@~2.4.11", "@volar/language-core@2.4.11":
"@volar/language-core@2.4.11", "@volar/language-core@~2.4.11":
version "2.4.11"
resolved "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.11.tgz"
integrity sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==
@@ -1654,14 +1759,6 @@
estree-walker "^2.0.2"
source-map-js "^1.2.0"
"@vue/compiler-dom@^3.5.0":
version "3.5.13"
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz"
integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==
dependencies:
"@vue/compiler-core" "3.5.13"
"@vue/shared" "3.5.13"
"@vue/compiler-dom@3.3.4":
version "3.3.4"
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz"
@@ -1670,6 +1767,14 @@
"@vue/compiler-core" "3.3.4"
"@vue/shared" "3.3.4"
"@vue/compiler-dom@^3.5.0":
version "3.5.13"
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz"
integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==
dependencies:
"@vue/compiler-core" "3.5.13"
"@vue/shared" "3.5.13"
"@vue/compiler-sfc@3.3.4":
version "3.3.4"
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz"
@@ -1781,12 +1886,12 @@
"@vue/compiler-ssr" "3.3.4"
"@vue/shared" "3.3.4"
"@vue/shared@^3.0.0", "@vue/shared@3.3.4":
"@vue/shared@3.3.4", "@vue/shared@^3.0.0":
version "3.3.4"
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz"
integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
"@vue/shared@^3.5.0", "@vue/shared@3.5.13":
"@vue/shared@3.5.13", "@vue/shared@^3.5.0":
version "3.5.13"
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz"
integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==
@@ -1828,7 +1933,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.8.2, acorn@^8.9.0:
acorn@^8.8.2, acorn@^8.9.0:
version "8.10.0"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz"
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
@@ -1843,7 +1948,7 @@ ajv@^6.12.4:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@^8.6.0, ajv@>=8:
ajv@^8.6.0:
version "8.12.0"
resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz"
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
@@ -1908,7 +2013,7 @@ anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
apexcharts@^3.44.0, "apexcharts@> 3.0.0":
apexcharts@^3.44.0:
version "3.44.0"
resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.44.0.tgz"
integrity sha512-u7Xzrbcxc2yWznN78Jh5NMCYVAsWDfBjRl5ea++rVzFAqjU2hLz4RgKIFwYOBDRQtW1e/Qz8azJTqIJ1+Vu9Qg==
@@ -2063,7 +2168,7 @@ braces@^3.0.3, braces@~3.0.2:
dependencies:
fill-range "^7.1.1"
browserslist@^4.21.9, browserslist@^4.22.1, "browserslist@>= 4.21.0":
browserslist@^4.21.9, browserslist@^4.22.1:
version "4.22.1"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz"
integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==
@@ -2127,7 +2232,7 @@ chalk@^2.4.1:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.0.0:
chalk@^4.0.0, chalk@^4.0.2:
version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -2135,15 +2240,7 @@ chalk@^4.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.2:
version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0":
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3:
version "3.5.3"
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
@@ -2172,16 +2269,16 @@ color-convert@^2.0.1:
dependencies:
color-name "~1.1.4"
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
colorette@^2.0.20:
version "2.0.20"
resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz"
@@ -2569,7 +2666,7 @@ eslint-plugin-prettier@^5.0.0:
prettier-linter-helpers "^1.0.0"
synckit "^0.8.5"
eslint-plugin-vue@^9.0.0, eslint-plugin-vue@^9.15.1:
eslint-plugin-vue@^9.15.1:
version "9.17.0"
resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz"
integrity sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==
@@ -2590,15 +2687,7 @@ eslint-scope@^5.1.1:
esrecurse "^4.3.0"
estraverse "^4.1.1"
eslint-scope@^7.1.1:
version "7.2.2"
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz"
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
eslint-scope@^7.2.2:
eslint-scope@^7.1.1, eslint-scope@^7.2.2:
version "7.2.2"
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz"
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
@@ -2611,7 +2700,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint@*, "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^6.2.0 || ^7.0.0 || ^8.0.0", eslint@^8.45.0, "eslint@>= 8.0.0", eslint@>=6.0.0, eslint@>=7.0.0, eslint@>=8.0.0:
eslint@^8.45.0:
version "8.47.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz"
integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==
@@ -2682,12 +2771,7 @@ estraverse@^4.1.1:
resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
estraverse@^5.1.0:
version "5.3.0"
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
estraverse@^5.2.0:
estraverse@^5.1.0, estraverse@^5.2.0:
version "5.3.0"
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
@@ -2712,22 +2796,7 @@ eventemitter3@^5.0.1:
resolved "https://mirror-npm.runflare.com/eventemitter3/-/eventemitter3-5.0.4.tgz"
integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==
execa@^5.0.0:
version "5.1.1"
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.0"
human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.1"
onetime "^5.1.2"
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
execa@^5.1.1:
execa@^5.0.0, execa@^5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
@@ -2873,6 +2942,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
fsevents@~2.3.2:
version "2.3.3"
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
@@ -2926,7 +3000,7 @@ get-symbol-description@^1.0.0:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
glob-parent@^5.1.2:
glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@@ -2940,13 +3014,6 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
glob@^7.1.3, glob@^7.1.6:
version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
@@ -3458,7 +3525,7 @@ kolorist@^1.8.0:
resolved "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz"
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
less@*, less@^4.2.0:
less@^4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/less/-/less-4.2.0.tgz"
integrity sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==
@@ -3566,14 +3633,7 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
magic-string@^0.25.0:
version "0.25.9"
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz"
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
dependencies:
sourcemap-codec "^1.4.8"
magic-string@^0.25.7:
magic-string@^0.25.0, magic-string@^0.25.7:
version "0.25.9"
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz"
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
@@ -3715,7 +3775,7 @@ mrmime@^1.0.0:
resolved "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz"
integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==
ms@^2.1.1, ms@2.1.2:
ms@2.1.2, ms@^2.1.1:
version "2.1.2"
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
@@ -3840,7 +3900,7 @@ object.assign@^4.1.4:
has-symbols "^1.0.3"
object-keys "^1.1.1"
odometer@^0.4.8, odometer@latest:
odometer@^0.4.8:
version "0.4.8"
resolved "https://registry.npmjs.org/odometer/-/odometer-0.4.8.tgz"
integrity sha512-bfKuAhWE/qMCiX9bwX90c5bTpt7MDVeq1e6YsOHQrYokNhv9jhS5JbR9kg6i+FeWmDgalf3VUtwNx1aVaZ8cgg==
@@ -4064,7 +4124,7 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
prettier@^3.0.0, "prettier@>= 3.0.0", prettier@>=3.0.0:
prettier@^3.0.0:
version "3.0.2"
resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz"
integrity sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==
@@ -4234,14 +4294,14 @@ rollup-plugin-terser@^7.0.0:
serialize-javascript "^4.0.0"
terser "^5.0.0"
"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.0.0, rollup@^2.43.1:
rollup@^2.43.1:
version "2.79.2"
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz"
integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
optionalDependencies:
fsevents "~2.3.2"
rollup@^1.20.0||^2.0.0||^3.0.0, rollup@^3.27.1:
rollup@^3.27.1:
version "3.29.5"
resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz"
integrity sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==
@@ -4291,7 +4351,7 @@ safe-regex-test@^1.0.0:
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sass@*, sass@^1.69.4:
sass@^1.69.4:
version "1.69.5"
resolved "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz"
integrity sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==
@@ -4312,12 +4372,7 @@ scroll-into-view-if-needed@^2.2.25:
dependencies:
compute-scroll-into-view "^1.0.20"
semver@^5.5.0:
version "5.7.2"
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
semver@^5.6.0:
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0:
version "5.7.2"
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
@@ -4327,32 +4382,13 @@ semver@^6.3.1:
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.3.6:
semver@^7.3.6, semver@^7.3.7, semver@^7.5.4:
version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
semver@^7.3.7:
version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
semver@^7.5.4:
version "7.5.4"
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
"semver@2 || 3 || 4 || 5":
version "5.7.2"
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
serialize-javascript@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz"
@@ -4431,7 +4467,7 @@ slash@^3.0.0:
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1, "source-map-js@>=0.6.2 <2.0.0":
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
@@ -4586,14 +4622,7 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"
supports-color@^7.0.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"
supports-color@^7.1.0:
supports-color@^7.0.0, supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
@@ -4631,7 +4660,7 @@ svg.filter.js@^2.0.2:
dependencies:
svg.js "^2.2.5"
svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5, svg.js@>=2.3.x:
svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5:
version "2.7.1"
resolved "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz"
integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
@@ -4693,7 +4722,7 @@ tempy@^0.6.0:
type-fest "^0.16.0"
unique-string "^2.0.0"
terser@^5.0.0, terser@^5.4.0:
terser@^5.0.0:
version "5.24.0"
resolved "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz"
integrity sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==
@@ -4732,6 +4761,11 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"
tslib@2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
tslib@^1.8.1:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
@@ -4742,11 +4776,6 @@ tslib@^2.3.0, tslib@^2.5.0, tslib@^2.6.0:
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz"
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
tslib@2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
@@ -4810,7 +4839,7 @@ typed-array-length@^1.0.4:
for-each "^0.3.3"
is-typed-array "^1.1.9"
typescript@*, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@>=4.4.4, typescript@>=5.0.0, typescript@~5.1.6:
typescript@~5.1.6:
version "5.1.6"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz"
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
@@ -4985,7 +5014,7 @@ vite-plugin-pwa@^0.16.7:
workbox-build "^7.0.0"
workbox-window "^7.0.0"
"vite@^2.9.0 || ^3.0.0-0 || ^4.0.0", "vite@^3.1.0 || ^4.0.0 || ^5.0.0-0", vite@^4.0.0, vite@^4.4.6:
vite@^4.4.6:
version "4.5.14"
resolved "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz"
integrity sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==
@@ -5006,11 +5035,6 @@ vue-content-loader@^2.0.1:
resolved "https://registry.npmjs.org/vue-content-loader/-/vue-content-loader-2.0.1.tgz"
integrity sha512-pkof4+q2xmzNEdhqelxtJejeP/vQUJtLle4/v2ueG+HURqM9Q/GIGC8GJ2bVVWeLfTDET51jqimwQdmxJTlu0g==
vue-demi@^0.12.5:
version "0.12.5"
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz"
integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
vue-demi@>=0.14.5:
version "0.14.5"
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz"
@@ -5021,6 +5045,11 @@ vue-demi@>=0.14.6:
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz"
integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==
vue-demi@^0.12.5:
version "0.12.5"
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz"
integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
vue-eslint-parser@^9.1.1, vue-eslint-parser@^9.3.1:
version "9.3.1"
resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz"
@@ -5068,17 +5097,6 @@ vue-types@^3.0.0:
dependencies:
is-plain-object "3.0.1"
"vue@^2.0.0 || >=3.0.0", "vue@^2.6.14 || ^3.3.0", vue@^3, vue@^3.0.*, vue@^3.0.0, "vue@^3.0.0-0 || ^2.6.0", vue@^3.2.0, vue@^3.2.25, vue@^3.3.4, "vue@> 3.0.0", "vue@>= 2.0.0", vue@>=3.0.3, vue@>=3.2.0, "vue@2 || 3", vue@3.3.4, vue@latest:
version "3.3.4"
resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz"
integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==
dependencies:
"@vue/compiler-dom" "3.3.4"
"@vue/compiler-sfc" "3.3.4"
"@vue/runtime-dom" "3.3.4"
"@vue/server-renderer" "3.3.4"
"@vue/shared" "3.3.4"
vue3-apexcharts@^1.4.4:
version "1.4.4"
resolved "https://registry.npmjs.org/vue3-apexcharts/-/vue3-apexcharts-1.4.4.tgz"
@@ -5104,6 +5122,17 @@ vue3-otp-input@^0.4.1:
resolved "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.4.1.tgz"
integrity sha512-wVl9i3DcWlO0C7fBI9V+RIP3crm/1tY72fuhvb3YM2JfbLoYofB96aPl5AgFhA0Cse5bQEMYtIvOeiqW3rfbAw==
vue@^3.2.25, vue@^3.3.4:
version "3.3.4"
resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz"
integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==
dependencies:
"@vue/compiler-dom" "3.3.4"
"@vue/compiler-sfc" "3.3.4"
"@vue/runtime-dom" "3.3.4"
"@vue/server-renderer" "3.3.4"
"@vue/shared" "3.3.4"
warning@^4.0.0:
version "4.0.3"
resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz"
@@ -5321,7 +5350,7 @@ workbox-sw@7.0.0:
resolved "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz"
integrity sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==
workbox-window@^7.0.0, workbox-window@7.0.0:
workbox-window@7.0.0, workbox-window@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz"
integrity sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==