This commit is contained in:
marzban-dev
2025-02-21 19:59:41 +03:30
parent a954bb0a3a
commit 6a5fed38aa
+61 -28
View File
@@ -4,6 +4,7 @@
import useGetProduct from "~/composables/api/product/useGetProduct"; import useGetProduct from "~/composables/api/product/useGetProduct";
import { sanitize } from "isomorphic-dompurify"; import { sanitize } from "isomorphic-dompurify";
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
// state // state
@@ -12,47 +13,69 @@ const id = route.params.id as string | undefined;
const { data: product } = useGetProduct(id); const { data: product } = useGetProduct(id);
const quantity = ref(1); const selectedVariantId = ref(product.value!.variants[0].id);
const selectedQuantity = ref(1);
const selectedSlide = ref(product.value!.variants[0].images[0].id);
const selectedSlide = ref(0); // provide / inject
const { selectedVariant, changeSelectedVariant } = inject("productVariant") as ProductVariantProvideType;
// computed // computed
const slides = computed(() => {
return [
{
id: 0,
picture: product.value!.image1
},
{
id: 1,
picture: product.value?.image2 ?? product.value!.image1
},
{
id: 2,
picture: product.value!.image3 ?? product.value!.image1
}
];
});
const sanitizedProductDescription = computed(() => { const sanitizedProductDescription = computed(() => {
return sanitize(product.value!.description); return sanitize(product.value!.description);
}); });
// watch
watch(() => selectedVariantId.value, (newId) => {
const newVariant = product.value!.variants.find(variant => variant.id === newId)!;
changeSelectedVariant(newVariant);
}, {
immediate: true
});
watch(() => selectedVariant.value, (newValue) => {
selectedQuantity.value = 1;
selectedSlide.value = newValue.images[0].id;
});
</script> </script>
<template> <template>
<div class="flex gap-12 container pt-[5rem]"> <div class="flex gap-16 container pt-[5rem] pb-28">
<Slider <Slider
class="flex-1" class="flex-1"
v-model:selectedSlide="selectedSlide" v-model:selectedSlide="selectedSlide"
:slides="slides" :slides="selectedVariant.images"
/> />
<div class="flex-1 flex flex-col gap-3 mt-12"> <div class="flex-1 flex flex-col gap-3 mt-12">
<span class="typo-label-sm"> سامسونگ </span> <span class="typo-label-sm"> سامسونگ </span>
<h1 class="typo-h-2"> {{ product!.name }} </h1> <h1 class="typo-h-2"> {{ product!.name }} </h1>
<div class="flex w-full items-center justify-between"> <div class="flex w-full items-center justify-between h-[85px]">
<span class="typo-p-2xl"> {{ product!.price }} </span> <div class="flex items-end gap-4">
<div class="flex flex-col gap-2">
<span
v-if="selectedVariant.discount > 0"
class="typo-p-lg relative flex-center w-fit"
:class="'after:w-full after:h-[2px] after:bg-black after:absolute'"
>
{{ selectedVariant.price }}
</span>
<span
class="typo-p-2xl relative flex-center w-fit font-medium"
>
{{ selectedVariant.discount > 0 ? selectedVariant.price : selectedVariant.price }}
</span>
</div>
<div v-if="selectedVariant.discount > 0"
class="text-white bg-blue-500 mb-1 px-4 py-2 text-xs rounded-full flex items-center gap-1">
<Icon name="material-symbols:percent" class="size-4" />
{{ selectedVariant.discount }}
درصد تخفیف
</div>
</div>
<Rating /> <Rating />
</div> </div>
@@ -61,11 +84,21 @@ const sanitizedProductDescription = computed(() => {
v-html="sanitizedProductDescription" v-html="sanitizedProductDescription"
/> />
<div class="w-full flex flex-col gap-6 mt-4"> <div class="flex items-center gap-6 flex-wrap">
<ProductVariant
@click="variant.in_stock > 0 ? selectedVariantId = variant.id : undefined"
v-for="variant in product!.variants"
:key="variant.id"
:variantDetail="variant"
:isSelected="selectedVariantId === variant.id"
/>
</div>
<div class="w-full flex flex-col gap-6 mt-10">
<RemainQuantity <RemainQuantity
:maxQuantity="product!.in_stock" :maxQuantity="selectedVariant.in_stock"
:quantity="quantity" :quantity="selectedQuantity"
/> />
<div class="w-full flex gap-3 flex-col"> <div class="w-full flex gap-3 flex-col">
@@ -74,8 +107,8 @@ const sanitizedProductDescription = computed(() => {
افزودن به سبد خرید افزودن به سبد خرید
</Button> </Button>
<QuantityCounter <QuantityCounter
v-model="quantity" v-model="selectedQuantity"
:max="product!.in_stock" :max="selectedVariant.in_stock"
/> />
</div> </div>
<Button class="w-full rounded-full" variant="outlined"> <Button class="w-full rounded-full" variant="outlined">