feat: new price count
This commit is contained in:
parent
63d31fbe53
commit
0130b9aa0d
|
@ -1,3 +1,3 @@
|
||||||
export { ProductCard, ProductImage } from './ui'
|
export { ProductCard, ProductImage, ProductPrice } from './ui'
|
||||||
|
|
||||||
export * as productModel from './model'
|
export * as productModel from './model'
|
||||||
|
|
|
@ -1,58 +1,63 @@
|
||||||
import { watchOnce } from '@vueuse/shared'
|
import { useStorage } from '@vueuse/core'
|
||||||
import type { CrmVariant } from '~/src/shared/model'
|
import type { CrmVariant } from '~/src/shared/model'
|
||||||
|
import { useCRMGetCart } from '~/src/shared/api/crm/crm'
|
||||||
|
|
||||||
export function useProductPrice() {
|
export function useProductPrice(variants: CrmVariant[], id: string) {
|
||||||
const amount = ref(0)
|
const amount = ref(0)
|
||||||
const currentUnitPrice = ref(0)
|
const currentUnitPrice = ref(0)
|
||||||
const prevUnitPrice = ref()
|
const prevUnitPrice = ref()
|
||||||
const variants = ref<CrmVariant[]>([])
|
const { mutateAsync, data } = useCRMGetCart()
|
||||||
|
|
||||||
|
const addedItems = useStorage<{
|
||||||
|
id: string
|
||||||
|
count: number
|
||||||
|
}[]>('added-items', [])
|
||||||
|
|
||||||
const currentPriceForAll = computed(() => currentUnitPrice.value * amount.value)
|
const currentPriceForAll = computed(() => currentUnitPrice.value * amount.value)
|
||||||
|
|
||||||
const prevUnitPriceForAll = computed(() => prevUnitPrice.value * amount.value)
|
const prevUnitPriceForAll = computed(() => prevUnitPrice.value * amount.value)
|
||||||
|
|
||||||
watch(amount, () => {
|
const setInitCurrentPrice = () => {
|
||||||
updatePrices()
|
currentUnitPrice.value = Number(variants[0].price) / 100
|
||||||
})
|
|
||||||
|
|
||||||
watchOnce(variants, () => {
|
|
||||||
updatePrices()
|
|
||||||
})
|
|
||||||
|
|
||||||
function updatePrices() {
|
|
||||||
if (!variants.value.length) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < variants.value.length; i++) {
|
watch(amount, async (value, oldValue) => {
|
||||||
const variant = variants.value[i]
|
await mutateAsync({
|
||||||
|
data: [
|
||||||
let max = Number.POSITIVE_INFINITY
|
{
|
||||||
let min = 0
|
count: String(value),
|
||||||
|
productId: id,
|
||||||
variant.properties?.forEach((property) => {
|
},
|
||||||
if (property.name === 'min') {
|
],
|
||||||
min = Number(property.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property.name === 'max')
|
|
||||||
max = Number(property.value)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (amount.value >= min && amount.value <= max) {
|
const newCurrent = Number(data.value?.data.amount) / 100 || 0
|
||||||
currentUnitPrice.value = Number(variant.price) / 100
|
const newPrev = Number(data.value?.data.amountOld) / 100 || 0
|
||||||
|
|
||||||
if (i !== 0) {
|
currentUnitPrice.value = newCurrent
|
||||||
prevUnitPrice.value = Number(variants.value[i - 1].price) / 100
|
|
||||||
|
if (newCurrent !== newPrev) {
|
||||||
|
prevUnitPrice.value = newPrev
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prevUnitPrice.value = undefined
|
prevUnitPrice.value = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
if (oldValue === 0 && value > 0) {
|
||||||
}
|
addedItems.value.push({
|
||||||
|
id,
|
||||||
|
count: value,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldValue > 0 && value === 0) {
|
||||||
|
addedItems.value = addedItems.value.filter(item => item.id !== id)
|
||||||
|
|
||||||
|
setInitCurrentPrice()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setInitCurrentPrice()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
amount,
|
amount,
|
||||||
|
@ -60,6 +65,5 @@ export function useProductPrice() {
|
||||||
prevUnitPrice,
|
prevUnitPrice,
|
||||||
currentPriceForAll,
|
currentPriceForAll,
|
||||||
prevUnitPriceForAll,
|
prevUnitPriceForAll,
|
||||||
variants,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,7 @@ const props = defineProps<{
|
||||||
product: CrmProduct
|
product: CrmProduct
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { amount, currentUnitPrice, prevUnitPriceForAll, prevUnitPrice, variants } = useProductPrice()
|
const { amount, currentUnitPrice, prevUnitPriceForAll, prevUnitPrice } = useProductPrice(props.product.variants || [], props.product.id!)
|
||||||
|
|
||||||
if (props.product.variants) {
|
|
||||||
variants.value = props.product.variants
|
|
||||||
}
|
|
||||||
|
|
||||||
function onImageClick() {
|
function onImageClick() {
|
||||||
navigateTo(
|
navigateTo(
|
||||||
|
@ -33,7 +29,7 @@ function onImageClick() {
|
||||||
<div>{{ product.name }}</div>
|
<div>{{ product.name }}</div>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<div class="text-2xl font-bold" :class="{ 'text-pink-800': prevUnitPrice }">
|
<div class="text-2xl font-bold" :class="{ 'text-pink-800': prevUnitPrice }">
|
||||||
{{ currentUnitPrice * (amount || 1) }} ₽
|
{{ currentUnitPrice }} ₽
|
||||||
</div>
|
</div>
|
||||||
<div v-if="prevUnitPrice" class="line-through text-slate-400">
|
<div v-if="prevUnitPrice" class="line-through text-slate-400">
|
||||||
{{ prevUnitPriceForAll }} ₽
|
{{ prevUnitPriceForAll }} ₽
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useProductPrice } from '../model'
|
||||||
|
import { InputNumber } from '~/src/shared/ui'
|
||||||
|
import type { CrmVariant } from '~/src/shared/model'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
variants: CrmVariant[]
|
||||||
|
productId: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { amount, currentUnitPrice, prevUnitPrice, prevUnitPriceForAll } = useProductPrice(props.variants, props.productId)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bg-gray-50 rounded-2xl border border-slate-200 flex gap-5 justify-between p-5 items-center">
|
||||||
|
<div class="flex flex-col gap-1 flex-1">
|
||||||
|
<div class="text-2xl font-bold" :class="{ 'text-pink-800': prevUnitPrice }">
|
||||||
|
{{ currentUnitPrice }} ₽
|
||||||
|
</div>
|
||||||
|
<div v-if="prevUnitPrice" class="line-through text-slate-400">
|
||||||
|
{{ prevUnitPriceForAll }} ₽
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<UButton v-if="!amount" class="w-full justify-center" size="xl" @click="amount = 1">
|
||||||
|
В корзину
|
||||||
|
</UButton>
|
||||||
|
<InputNumber v-else v-model="amount" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,2 +1,3 @@
|
||||||
export { default as ProductCard } from './ProductCard.vue'
|
export { default as ProductCard } from './ProductCard.vue'
|
||||||
export { default as ProductImage } from './ProductImage.vue'
|
export { default as ProductImage } from './ProductImage.vue'
|
||||||
|
export { default as ProductPrice } from './ProductPrice.vue'
|
||||||
|
|
|
@ -1,22 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { watchOnce } from '@vueuse/shared'
|
import { ProductImage, ProductPrice } from '~/src/entities/product'
|
||||||
import { ProductImage, productModel } from '~/src/entities/product'
|
|
||||||
import { useCRMGetProduct } from '~/src/shared/api/crm/crm'
|
import { useCRMGetProduct } from '~/src/shared/api/crm/crm'
|
||||||
import { Header } from '~/src/widgets/header'
|
import { Header } from '~/src/widgets/header'
|
||||||
import { InputNumber, StandardLayout } from '~/src/shared/ui'
|
import { StandardLayout } from '~/src/shared/ui'
|
||||||
import { Footer } from '~/src/widgets/footer'
|
import { Footer } from '~/src/widgets/footer'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const { data } = useCRMGetProduct(route.params.id as string)
|
const { data } = useCRMGetProduct(route.params.id as string)
|
||||||
|
|
||||||
const { amount, currentUnitPrice, prevUnitPrice, prevUnitPriceForAll, variants } = productModel.useProductPrice()
|
|
||||||
|
|
||||||
watchOnce(() => data.value?.data.product?.variants, (value) => {
|
|
||||||
if (value) {
|
|
||||||
variants.value = value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -38,22 +29,11 @@ watchOnce(() => data.value?.data.product?.variants, (value) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="data?.data.product" class="bg-gray-50 rounded-2xl border border-slate-200 flex gap-5 justify-between p-5 items-center">
|
<ProductPrice
|
||||||
<div class="flex flex-col gap-1 flex-1">
|
v-if="data?.data.product?.id && data.data.product.variants"
|
||||||
<div class="text-2xl font-bold" :class="{ 'text-pink-800': prevUnitPrice }">
|
:product-id="data.data.product.id"
|
||||||
{{ currentUnitPrice * (amount || 1) }} ₽
|
:variants="data.data.product.variants"
|
||||||
</div>
|
/>
|
||||||
<div v-if="prevUnitPrice" class="line-through text-slate-400">
|
|
||||||
{{ prevUnitPriceForAll }} ₽
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1">
|
|
||||||
<UButton v-if="!amount" class="w-full justify-center" size="xl" @click="amount = 1">
|
|
||||||
В корзину
|
|
||||||
</UButton>
|
|
||||||
<InputNumber v-else v-model="amount" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
Loading…
Reference in New Issue