show price in product editor
This commit is contained in:
@@ -117,28 +117,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-2 rounded-lg border border-solid border-blue-200 bg-blue-50 p-3">
|
<div class="mt-2 rounded-lg border border-solid border-blue-200 bg-blue-50 px-3 py-2">
|
||||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
<div class="flex flex-col gap-2 md:flex-row md:items-center md:justify-between md:gap-3">
|
||||||
<div class="text-sm font-600 text-gray-700">قیمت لحظهای</div>
|
<div class="flex flex-wrap items-center gap-x-3 gap-y-1 md:min-w-0 md:flex-1">
|
||||||
<AButton size="small" :loading="pricesLoading || appPriceLoading" @click="$emit('refreshPrices')">
|
<span class="shrink-0 text-sm font-600 text-gray-700">قیمت لحظهای:</span>
|
||||||
|
<span v-if="livePricePreview.status === 'ready'" class="text-base font-700 text-blue-700">
|
||||||
|
{{ usePrice(livePricePreview.amount) }}
|
||||||
|
</span>
|
||||||
|
<span v-else-if="livePricePreview.message" class="text-sm text-gray-500">
|
||||||
|
{{ livePricePreview.message }}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="livePricePreview.status === 'ready'"
|
||||||
|
class="truncate text-xs text-gray-500"
|
||||||
|
>
|
||||||
|
مبنا: {{ livePricePreview.source }}
|
||||||
|
<span v-if="Number(form.price_offset_percent) !== 0">
|
||||||
|
— تعدیل {{ form.price_offset_percent }}٪
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<AButton size="small" class="shrink-0 self-end md:self-auto" @click="$emit('refreshPrices')">
|
||||||
بروزرسانی
|
بروزرسانی
|
||||||
</AButton>
|
</AButton>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="livePricePreview.status === 'ready'" class="mt-2 text-lg font-700 text-blue-700">
|
|
||||||
{{ usePrice(livePricePreview.amount) }}
|
|
||||||
</div>
|
|
||||||
<div v-else-if="livePricePreview.status === 'loading'" class="mt-2 text-sm text-gray-500">
|
|
||||||
{{ livePricePreview.message }}
|
|
||||||
</div>
|
|
||||||
<div v-else class="mt-2 text-sm text-gray-500">
|
|
||||||
{{ livePricePreview.message }}
|
|
||||||
</div>
|
|
||||||
<div v-if="livePricePreview.status === 'ready'" class="mt-1 text-xs text-gray-500">
|
|
||||||
مبنا: {{ livePricePreview.source }}
|
|
||||||
<span v-if="Number(form.price_offset_percent) !== 0">
|
|
||||||
— تعدیل {{ form.price_offset_percent }}٪
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -247,9 +249,7 @@ const props = defineProps<{
|
|||||||
activeKey: string[]
|
activeKey: string[]
|
||||||
pricesList: Array<{ id: string; name: string }>
|
pricesList: Array<{ id: string; name: string }>
|
||||||
pricesData: MethodePrices[]
|
pricesData: MethodePrices[]
|
||||||
pricesLoading: boolean
|
|
||||||
appLastPrice: (last & { price?: number }) | null
|
appLastPrice: (last & { price?: number }) | null
|
||||||
appPriceLoading: boolean
|
|
||||||
categoryItems: any[]
|
categoryItems: any[]
|
||||||
metalItems: any[]
|
metalItems: any[]
|
||||||
priceItems: any[]
|
priceItems: any[]
|
||||||
@@ -268,9 +268,7 @@ const livePricePreview = computed(() =>
|
|||||||
methodOption: props.methodOption,
|
methodOption: props.methodOption,
|
||||||
meltedPriceOption: props.meltedPriceOption as 'app' | 'fixed' | 'reference',
|
meltedPriceOption: props.meltedPriceOption as 'app' | 'fixed' | 'reference',
|
||||||
pricesData: props.pricesData,
|
pricesData: props.pricesData,
|
||||||
appLastPrice: props.appLastPrice,
|
appLastPrice: props.appLastPrice
|
||||||
pricesLoading: props.pricesLoading,
|
|
||||||
appPriceLoading: props.appPriceLoading
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,7 @@
|
|||||||
:activeKey="activeKey_"
|
:activeKey="activeKey_"
|
||||||
:pricesList="pricesList"
|
:pricesList="pricesList"
|
||||||
:pricesData="pricesData"
|
:pricesData="pricesData"
|
||||||
:pricesLoading="pricesLoading"
|
|
||||||
:appLastPrice="appLastPrice"
|
:appLastPrice="appLastPrice"
|
||||||
:appPriceLoading="appPriceLoading"
|
|
||||||
:categoryItems="categorySelectItems"
|
:categoryItems="categorySelectItems"
|
||||||
:metalItems="metalItems"
|
:metalItems="metalItems"
|
||||||
:priceItems="priceItems"
|
:priceItems="priceItems"
|
||||||
@@ -129,9 +127,7 @@ const priceItems: Array<Item> = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const pricesData = ref<MethodePrices[]>([])
|
const pricesData = ref<MethodePrices[]>([])
|
||||||
const pricesLoading = ref(false)
|
|
||||||
const appLastPrice = ref<(last & { price?: number }) | null>(null)
|
const appLastPrice = ref<(last & { price?: number }) | null>(null)
|
||||||
const appPriceLoading = ref(false)
|
|
||||||
let pricePollTimer: ReturnType<typeof setInterval> | undefined
|
let pricePollTimer: ReturnType<typeof setInterval> | undefined
|
||||||
|
|
||||||
const pricesList = computed(() =>
|
const pricesList = computed(() =>
|
||||||
@@ -142,25 +138,19 @@ const pricesList = computed(() =>
|
|||||||
)
|
)
|
||||||
|
|
||||||
async function fetchPrices() {
|
async function fetchPrices() {
|
||||||
pricesLoading.value = true
|
|
||||||
try {
|
try {
|
||||||
pricesData.value = await methodePrices()
|
pricesData.value = await methodePrices()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
} finally {
|
|
||||||
pricesLoading.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchAppPrice() {
|
async function fetchAppPrice() {
|
||||||
appPriceLoading.value = true
|
|
||||||
try {
|
try {
|
||||||
appLastPrice.value = await getLastPrice()
|
appLastPrice.value = await getLastPrice()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
appLastPrice.value = null
|
appLastPrice.value = null
|
||||||
} finally {
|
|
||||||
appPriceLoading.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ export function resolveAppBasePrice(lastPrice?: Partial<last> & { price?: number
|
|||||||
export type ProductEditorPricePreview =
|
export type ProductEditorPricePreview =
|
||||||
| { status: 'ready'; amount: number; source: string }
|
| { status: 'ready'; amount: number; source: string }
|
||||||
| { status: 'empty'; message: string }
|
| { status: 'empty'; message: string }
|
||||||
| { status: 'loading'; message: string }
|
|
||||||
|
|
||||||
export function computeProductEditorPricePreview(input: {
|
export function computeProductEditorPricePreview(input: {
|
||||||
form: {
|
form: {
|
||||||
@@ -68,8 +67,6 @@ export function computeProductEditorPricePreview(input: {
|
|||||||
meltedPriceOption: MeltedPriceSource
|
meltedPriceOption: MeltedPriceSource
|
||||||
pricesData: MethodePrices[]
|
pricesData: MethodePrices[]
|
||||||
appLastPrice?: (Partial<last> & { price?: number }) | null
|
appLastPrice?: (Partial<last> & { price?: number }) | null
|
||||||
pricesLoading?: boolean
|
|
||||||
appPriceLoading?: boolean
|
|
||||||
}): ProductEditorPricePreview {
|
}): ProductEditorPricePreview {
|
||||||
const offsetPercent = Number(input.form.price_offset_percent ?? 0)
|
const offsetPercent = Number(input.form.price_offset_percent ?? 0)
|
||||||
const melted = isMeltedTradeGroup(input.form.group_type)
|
const melted = isMeltedTradeGroup(input.form.group_type)
|
||||||
@@ -83,12 +80,9 @@ export function computeProductEditorPricePreview(input: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (input.meltedPriceOption === 'app') {
|
if (input.meltedPriceOption === 'app') {
|
||||||
if (input.appPriceLoading) {
|
|
||||||
return { status: 'loading', message: 'در حال دریافت قیمت اپ...' }
|
|
||||||
}
|
|
||||||
const base = resolveAppBasePrice(input.appLastPrice)
|
const base = resolveAppBasePrice(input.appLastPrice)
|
||||||
if (base <= 0) {
|
if (base <= 0) {
|
||||||
return { status: 'empty', message: 'قیمت اپ در دسترس نیست' }
|
return { status: 'empty', message: '' }
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
status: 'ready',
|
status: 'ready',
|
||||||
@@ -100,12 +94,9 @@ export function computeProductEditorPricePreview(input: {
|
|||||||
if (!input.form.reading_method) {
|
if (!input.form.reading_method) {
|
||||||
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
|
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
|
||||||
}
|
}
|
||||||
if (input.pricesLoading) {
|
|
||||||
return { status: 'loading', message: 'در حال دریافت قیمت مرجع...' }
|
|
||||||
}
|
|
||||||
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
|
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return { status: 'empty', message: 'مرجع قیمت یافت نشد' }
|
return { status: 'empty', message: '' }
|
||||||
}
|
}
|
||||||
const { base, profit } = normalizeReferenceBase(entry)
|
const { base, profit } = normalizeReferenceBase(entry)
|
||||||
return {
|
return {
|
||||||
@@ -125,12 +116,9 @@ export function computeProductEditorPricePreview(input: {
|
|||||||
if (!input.form.reading_method) {
|
if (!input.form.reading_method) {
|
||||||
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
|
return { status: 'empty', message: 'مرجع قیمت را انتخاب کنید' }
|
||||||
}
|
}
|
||||||
if (input.pricesLoading) {
|
|
||||||
return { status: 'loading', message: 'در حال دریافت قیمت مرجع...' }
|
|
||||||
}
|
|
||||||
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
|
const entry = findMethodPriceEntry(input.pricesData, input.form.reading_method)
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return { status: 'empty', message: 'مرجع قیمت یافت نشد' }
|
return { status: 'empty', message: '' }
|
||||||
}
|
}
|
||||||
const { base, profit } = normalizeReferenceBase(entry)
|
const { base, profit } = normalizeReferenceBase(entry)
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user