This commit is contained in:
marzban-dev
2025-04-16 22:13:13 +03:30
parent a71d40987e
commit bdf9d6d0cd
+77 -52
View File
@@ -1,5 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
// import // import
import useGetProduct from "~/composables/api/product/useGetProduct"; import useGetProduct from "~/composables/api/product/useGetProduct";
@@ -31,61 +30,78 @@ const { selectedVariant, changeSelectedVariant } = inject("productVariant") as P
const addItemToCart = async () => { const addItemToCart = async () => {
await addCartItem({ await addCartItem({
id: selectedVariant.value!.id, id: selectedVariant.value!.id,
quantity: selectedQuantity.value quantity: selectedQuantity.value,
}); });
await refetchProduct(); await refetchProduct();
}; };
// watch // watch
watch(() => selectedVariantId.value, (newId) => { watch(
const newVariant = product.value!.variants.find(variant => variant.id === newId)!; () => selectedVariantId.value,
changeSelectedVariant(newVariant); (newId) => {
}); const newVariant = product.value!.variants.find((variant) => variant.id === newId)!;
changeSelectedVariant(newVariant);
}
);
watch(() => selectedColor.value, (newValue) => { watch(
const filteredVariants = product.value!.variants.filter(v => v.color === newValue); () => selectedColor.value,
selectedVariantId.value = filteredVariants[0].id; (newValue) => {
selectedVariant.value = filteredVariants[0]; const filteredVariants = product.value!.variants.filter((v) => v.color === newValue);
}, { selectedVariantId.value = filteredVariants[0].id;
immediate: true selectedVariant.value = filteredVariants[0];
}); },
{
watch(() => selectedVariant.value!, (newValue) => { immediate: true,
selectedQuantity.value = 1; }
selectedSlide.value = newValue.images[0].id; );
});
watch(
() => selectedVariant.value!,
(newValue) => {
selectedQuantity.value = 1;
selectedSlide.value = newValue.images[0].id;
}
);
</script> </script>
<template> <template>
<div class="flex max-lg:flex-col gap-12 xl:gap-16 container pt-[5rem] pb-28"> <div class="flex max-lg:flex-col gap-12 xl:gap-16 container pt-[5rem] pb-28">
<div class="flex flex-col gap-3 lg:hidden"> <div class="flex flex-col gap-3 lg:hidden">
<NuxtLink to="#" class="typo-label-sm"> {{ product!.category.name }}</NuxtLink> <NuxtLink
<h1 class="typo-h-6 xs:typo-h-5 sm:typo-h-4 lg:typo-h-2"> {{ product!.name }} </h1> to="#"
class="typo-label-sm"
>
{{ product!.category.name }}</NuxtLink
>
<h1 class="typo-h-6 xs:typo-h-5 sm:typo-h-4 lg:typo-h-2">
{{ product!.name }}
</h1>
<div class="flex w-full items-center justify-between h-[85px]"> <div class="flex w-full items-center justify-between h-[85px]">
<div class="flex items-end gap-4"> <div class="flex items-end gap-4">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<span <span
v-if="selectedVariant!.discount > 0" v-if="selectedVariant!.discount > 0"
class="typo-p-lg relative flex-center w-fit" class="typo-p-md sm:typo-p-lg relative flex-center w-fit"
:class="'after:w-full after:h-[2px] after:bg-black after:absolute'" :class="'after:w-full after:h-[2px] after:bg-black after:absolute'"
> >
{{ selectedVariant!.price }} {{ selectedVariant!.price }}
</span> </span>
<span <span class="typo-p-md sm:typo-p-2xl relative flex-center w-fit font-medium">
class="typo-p-2xl relative flex-center w-fit font-medium"
>
{{ selectedVariant!.discount > 0 ? selectedVariant!.price : selectedVariant!.price }} {{ selectedVariant!.discount > 0 ? selectedVariant!.price : selectedVariant!.price }}
</span> </span>
</div> </div>
<div <div
v-if="selectedVariant!.discount > 0" 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" class="text-white bg-blue-500 mb-1 px-3 sm:px-4 py-1.5 sm:py-2 text-xs rounded-full flex items-center gap-1"
> >
<Icon name="material-symbols:percent" class="size-4" /> <Icon
name="material-symbols:percent"
class="size-3.5 sm:size-4"
/>
{{ selectedVariant!.discount }} {{ selectedVariant!.discount }}
درصد تخفیف <span class="max-sm:hidden"> تخفیف درصد </span>
</div> </div>
</div> </div>
<Rating :rate="3" /> <Rating :rate="3" />
@@ -103,7 +119,9 @@ watch(() => selectedVariant.value!, (newValue) => {
> >
{{ product!.category.name }} {{ product!.category.name }}
</NuxtLink> </NuxtLink>
<h1 class="typo-h-4 xl:typo-h-3 max-lg:hidden"> {{ product!.name }} </h1> <h1 class="typo-h-4 xl:typo-h-3 max-lg:hidden">
{{ product!.name }}
</h1>
<div class="flex w-full items-center justify-between h-[85px] max-lg:hidden"> <div class="flex w-full items-center justify-between h-[85px] max-lg:hidden">
<div class="flex items-end gap-4"> <div class="flex items-end gap-4">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@@ -114,9 +132,7 @@ watch(() => selectedVariant.value!, (newValue) => {
> >
{{ selectedVariant!.price }} {{ selectedVariant!.price }}
</span> </span>
<span <span class="typo-p-2xl relative flex-center w-fit font-medium">
class="typo-p-2xl relative flex-center w-fit font-medium"
>
{{ selectedVariant!.discount > 0 ? selectedVariant!.price : selectedVariant!.price }} {{ selectedVariant!.discount > 0 ? selectedVariant!.price : selectedVariant!.price }}
</span> </span>
</div> </div>
@@ -124,37 +140,42 @@ watch(() => selectedVariant.value!, (newValue) => {
v-if="selectedVariant!.discount > 0" 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" 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" /> <Icon
name="material-symbols:percent"
class="size-4"
/>
{{ selectedVariant!.discount }} {{ selectedVariant!.discount }}
<span class="max-sm:hidden">درصد</span> <span class="max-sm:hidden">درصد</span>
تخفیف تخفیف
</div> </div>
<Rating :rate="3" class="sm:hidden" /> <Rating
:rate="3"
class="sm:hidden"
/>
</div> </div>
<Rating :rate="3" class="max-sm:hidden" /> <Rating
:rate="3"
class="max-sm:hidden"
/>
</div> </div>
<div <div
class="py-8 typo-p-md text-slate-500 text-justify [&_a]:text-blue-400 [&_strong]:font-bold [&_u]:text-red-400" class="py-8 typo-sm max-sm:leading-[175%] sm:typo-p-md text-slate-500 text-justify [&_a]:text-blue-400 [&_strong]:font-bold [&_u]:text-red-400"
v-html="product!.description" v-html="product!.description"
/> />
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<span class="typo-p-lg"> <span class="typo-md sm:typo-p-lg"> تنوع رنگی : </span>
تنوع رنگی :
</span>
<div class="flex items-center gap-4 py-4"> <div class="flex items-center gap-4 py-4">
<ColorCircle <ColorCircle
v-for="color in product!.colors" v-for="color in product!.colors"
:key="color" :key="color"
@click="selectedColor = color" @click="selectedColor = color"
selectable selectable
:selected="selectedColor === color " :selected="selectedColor === color"
:style="{backgroundColor: color}" :style="{ backgroundColor: color }"
class="cursor-pointer" class="cursor-pointer"
/> />
</div> </div>
@@ -162,7 +183,7 @@ watch(() => selectedVariant.value!, (newValue) => {
<div class="flex items-center gap-6 flex-wrap"> <div class="flex items-center gap-6 flex-wrap">
<ProductVariant <ProductVariant
@click="variant.in_stock > 0 ? selectedVariantId = variant.id : undefined" @click="variant.in_stock > 0 ? (selectedVariantId = variant.id) : undefined"
v-for="variant in product!.variants.filter(p => p.color === selectedColor)" v-for="variant in product!.variants.filter(p => p.color === selectedColor)"
:key="variant.id" :key="variant.id"
:variantDetail="variant" :variantDetail="variant"
@@ -171,7 +192,6 @@ watch(() => selectedVariant.value!, (newValue) => {
</div> </div>
<div class="w-full flex flex-col gap-6 mt-10"> <div class="w-full flex flex-col gap-6 mt-10">
<RemainQuantity <RemainQuantity
:maxQuantity="selectedVariant!.in_stock" :maxQuantity="selectedVariant!.in_stock"
:quantity="selectedQuantity" :quantity="selectedQuantity"
@@ -184,24 +204,31 @@ watch(() => selectedVariant.value!, (newValue) => {
@click="addItemToCart" @click="addItemToCart"
:loading="isAddCartItemPending" :loading="isAddCartItemPending"
:disabled="isAddCartItemPending" :disabled="isAddCartItemPending"
class="w-full rounded-full" class="w-full rounded-full max-sm:h-[48px]"
end-icon="ci:plus" end-icon="ci:plus"
> >
افزودن به سبد خرید افزودن به سبد خرید
</Button> </Button>
<NuxtLink v-else to="/cart" class="w-full"> <NuxtLink
v-else
to="/cart"
class="w-full"
>
<Button <Button
class="w-full rounded-full h-full" class="w-full rounded-full h-full max-sm:h-[48px]"
end-icon="ci:cart" end-icon="ci:cart"
> >
مشاهده در سبد خرید مشاهده در سبد خرید
</Button> </Button>
</NuxtLink> </NuxtLink>
</template> </template>
<NuxtLink v-else to="/signin" class="w-full"> <NuxtLink
v-else
to="/signin"
class="w-full"
>
<Button <Button
class="w-full rounded-full h-full" class="w-full rounded-full h-full max-sm:h-[48px]"
end-icon="ci:user" end-icon="ci:user"
> >
ابتدا وارد شوید ابتدا وارد شوید
@@ -216,13 +243,11 @@ watch(() => selectedVariant.value!, (newValue) => {
/> />
<UpdateQuantity v-else /> <UpdateQuantity v-else />
</div> </div>
<InfoCard /> <InfoCard />
<Share /> <Share />
</div> </div>
</div> </div>
</div> </div>