feat: add description

This commit is contained in:
Константин Уколов 2024-08-31 14:04:49 +03:00
parent 1fd9fd292d
commit 63d31fbe53
7 changed files with 123 additions and 60 deletions

View File

@ -7,7 +7,7 @@ export default defineConfig({
target: 'src/shared/api', target: 'src/shared/api',
schemas: 'src/shared/model', schemas: 'src/shared/model',
client: 'vue-query', client: 'vue-query',
baseUrl: 'https://cake-crm.3crabs.ru', baseUrl: 'https://cake-api.3crabs.ru',
// mock: true, // mock: true,
}, },
input: './cakes.json', input: './cakes.json',

View File

@ -1 +1,3 @@
export { ProductCard, ProductImage } from './ui' export { ProductCard, ProductImage } from './ui'
export * as productModel from './model'

View File

@ -0,0 +1 @@
export { useProductPrice } from './use-product-price'

View File

@ -0,0 +1,65 @@
import { watchOnce } from '@vueuse/shared'
import type { CrmVariant } from '~/src/shared/model'
export function useProductPrice() {
const amount = ref(0)
const currentUnitPrice = ref(0)
const prevUnitPrice = ref()
const variants = ref<CrmVariant[]>([])
const currentPriceForAll = computed(() => currentUnitPrice.value * amount.value)
const prevUnitPriceForAll = computed(() => prevUnitPrice.value * amount.value)
watch(amount, () => {
updatePrices()
})
watchOnce(variants, () => {
updatePrices()
})
function updatePrices() {
if (!variants.value.length) {
return
}
for (let i = 0; i < variants.value.length; i++) {
const variant = variants.value[i]
let max = Number.POSITIVE_INFINITY
let min = 0
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) {
currentUnitPrice.value = Number(variant.price) / 100
if (i !== 0) {
prevUnitPrice.value = Number(variants.value[i - 1].price) / 100
}
else {
prevUnitPrice.value = undefined
}
return
}
}
}
return {
amount,
currentUnitPrice,
prevUnitPrice,
currentPriceForAll,
prevUnitPriceForAll,
variants,
}
}

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useProductPrice } from '../model'
import ProductImage from './ProductImage.vue' import ProductImage from './ProductImage.vue'
import { InputNumber } from '~/src/shared/ui' import { InputNumber } from '~/src/shared/ui'
import type { CrmProduct } from '~/src/shared/model' import type { CrmProduct } from '~/src/shared/model'
@ -7,52 +8,17 @@ const props = defineProps<{
product: CrmProduct product: CrmProduct
}>() }>()
const amount = ref(0) const { amount, currentUnitPrice, prevUnitPriceForAll, prevUnitPrice, variants } = useProductPrice()
const currentUnitPrice = ref(0)
const prevUnitPrice = ref() if (props.product.variants) {
variants.value = props.product.variants
}
function onImageClick() { function onImageClick() {
navigateTo( navigateTo(
`/products/${props.product.id}`, `/products/${props.product.id}`,
) )
} }
function updatePrices() {
if (!props.product.variants?.length) {
return
}
for (let i = 0; i < props.product.variants.length; i++) {
const variant = props.product.variants[i]
let max = Number.POSITIVE_INFINITY
let min = 0
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) {
currentUnitPrice.value = Number(variant.price) / 100
if (i !== 0) {
prevUnitPrice.value = Number(props.product.variants[i - 1].price) / 100
}
else {
prevUnitPrice.value = undefined
}
return
}
}
}
updatePrices()
</script> </script>
<template> <template>
@ -70,7 +36,7 @@ updatePrices()
{{ currentUnitPrice * (amount || 1) }} {{ currentUnitPrice * (amount || 1) }}
</div> </div>
<div v-if="prevUnitPrice" class="line-through text-slate-400"> <div v-if="prevUnitPrice" class="line-through text-slate-400">
{{ prevUnitPrice * amount }} {{ prevUnitPriceForAll }}
</div> </div>
</div> </div>
@ -78,7 +44,7 @@ updatePrices()
<UButton v-if="!amount" class="w-full justify-center" size="xl" @click="amount = 1"> <UButton v-if="!amount" class="w-full justify-center" size="xl" @click="amount = 1">
В корзину В корзину
</UButton> </UButton>
<InputNumber v-else v-model="amount" @update:model-value="updatePrices" /> <InputNumber v-else v-model="amount" />
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,13 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { ProductImage } from '~/src/entities/product' import { watchOnce } from '@vueuse/shared'
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 { StandardLayout } from '~/src/shared/ui' import { InputNumber, 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>
@ -23,7 +32,27 @@ const { data } = useCRMGetProduct(route.params.id as string)
</div> </div>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<div>Надо заполнить на бэке - тяжело тестить</div> <div v-for="characteristic in data?.data.product?.characteristics" :key="characteristic.name" class="flex gap-2 items-end">
<span class="font-bold">{{ characteristic.name }}:</span>
<span class="text-sm font-medium">{{ characteristic.value }}</span>
</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">
<div class="flex flex-col gap-1 flex-1">
<div class="text-2xl font-bold" :class="{ 'text-pink-800': prevUnitPrice }">
{{ currentUnitPrice * (amount || 1) }}
</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> </div>

View File

@ -51,7 +51,7 @@ export const cRMGetCart = (
): Promise<AxiosResponse<CrmCartRsp>> => { ): Promise<AxiosResponse<CrmCartRsp>> => {
crmOrderItem = unref(crmOrderItem); crmOrderItem = unref(crmOrderItem);
return axios.post( return axios.post(
`https://cake-crm.3crabs.ru/cart`, `https://cake-api.3crabs.ru/cart`,
crmOrderItem,options crmOrderItem,options
); );
} }
@ -99,13 +99,13 @@ const {mutation: mutationOptions, axios: axiosOptions} = options ?? {};
): Promise<AxiosResponse<CrmCatalogRsp>> => { ): Promise<AxiosResponse<CrmCatalogRsp>> => {
return axios.get( return axios.get(
`https://cake-crm.3crabs.ru/catalog`,options `https://cake-api.3crabs.ru/catalog`,options
); );
} }
export const getCRMGetCatalogQueryKey = () => { export const getCRMGetCatalogQueryKey = () => {
return ['https:','cake-crm.3crabs.ru','catalog'] as const; return ['https:','cake-api.3crabs.ru','catalog'] as const;
} }
@ -151,13 +151,13 @@ export const cRMGetImage = (
): Promise<AxiosResponse<ApiHttpBody>> => { ): Promise<AxiosResponse<ApiHttpBody>> => {
name = unref(name); name = unref(name);
return axios.get( return axios.get(
`https://cake-crm.3crabs.ru/images/${name}`,options `https://cake-api.3crabs.ru/images/${name}`,options
); );
} }
export const getCRMGetImageQueryKey = (name: MaybeRef<string>,) => { export const getCRMGetImageQueryKey = (name: MaybeRef<string>,) => {
return ['https:','cake-crm.3crabs.ru','images',name] as const; return ['https:','cake-api.3crabs.ru','images',name] as const;
} }
@ -203,7 +203,7 @@ export const cRMOrder = (
): Promise<AxiosResponse<CrmOrderRsp>> => { ): Promise<AxiosResponse<CrmOrderRsp>> => {
crabscrmOrder = unref(crabscrmOrder); crabscrmOrder = unref(crabscrmOrder);
return axios.post( return axios.post(
`https://cake-crm.3crabs.ru/orders`, `https://cake-api.3crabs.ru/orders`,
crabscrmOrder,options crabscrmOrder,options
); );
} }
@ -251,13 +251,13 @@ const {mutation: mutationOptions, axios: axiosOptions} = options ?? {};
): Promise<AxiosResponse<CrmPositionsRsp>> => { ): Promise<AxiosResponse<CrmPositionsRsp>> => {
id = unref(id); id = unref(id);
return axios.get( return axios.get(
`https://cake-crm.3crabs.ru/positions/${id}`,options `https://cake-api.3crabs.ru/positions/${id}`,options
); );
} }
export const getCRMGetPositionsQueryKey = (id: MaybeRef<string>,) => { export const getCRMGetPositionsQueryKey = (id: MaybeRef<string>,) => {
return ['https:','cake-crm.3crabs.ru','positions',id] as const; return ['https:','cake-api.3crabs.ru','positions',id] as const;
} }
@ -303,13 +303,13 @@ export const cRMGetProduct = (
): Promise<AxiosResponse<CrmProductRsp>> => { ): Promise<AxiosResponse<CrmProductRsp>> => {
id = unref(id); id = unref(id);
return axios.get( return axios.get(
`https://cake-crm.3crabs.ru/products/${id}`,options `https://cake-api.3crabs.ru/products/${id}`,options
); );
} }
export const getCRMGetProductQueryKey = (id: MaybeRef<string>,) => { export const getCRMGetProductQueryKey = (id: MaybeRef<string>,) => {
return ['https:','cake-crm.3crabs.ru','products',id] as const; return ['https:','cake-api.3crabs.ru','products',id] as const;
} }
@ -355,13 +355,13 @@ export const cRMGetBreadcrumbs = (
): Promise<AxiosResponse<CrmBreadcrumbsRsp>> => { ): Promise<AxiosResponse<CrmBreadcrumbsRsp>> => {
id = unref(id); id = unref(id);
return axios.get( return axios.get(
`https://cake-crm.3crabs.ru/products/${id}/breadcrumbs`,options `https://cake-api.3crabs.ru/products/${id}/breadcrumbs`,options
); );
} }
export const getCRMGetBreadcrumbsQueryKey = (id: MaybeRef<string>,) => { export const getCRMGetBreadcrumbsQueryKey = (id: MaybeRef<string>,) => {
return ['https:','cake-crm.3crabs.ru','products',id,'breadcrumbs'] as const; return ['https:','cake-api.3crabs.ru','products',id,'breadcrumbs'] as const;
} }
@ -407,7 +407,7 @@ export const cRMSearch = (
): Promise<AxiosResponse<CrmPositionsRsp>> => { ): Promise<AxiosResponse<CrmPositionsRsp>> => {
params = unref(params); params = unref(params);
return axios.get( return axios.get(
`https://cake-crm.3crabs.ru/search`,{ `https://cake-api.3crabs.ru/search`,{
...options, ...options,
params: {...unref(params), ...options?.params},} params: {...unref(params), ...options?.params},}
); );
@ -415,7 +415,7 @@ export const cRMSearch = (
export const getCRMSearchQueryKey = (params?: MaybeRef<CRMSearchParams>,) => { export const getCRMSearchQueryKey = (params?: MaybeRef<CRMSearchParams>,) => {
return ['https:','cake-crm.3crabs.ru','search', ...(params ? [params]: [])] as const; return ['https:','cake-api.3crabs.ru','search', ...(params ? [params]: [])] as const;
} }