Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -10,6 +10,7 @@ type Props = {
|
|||||||
description: string;
|
description: string;
|
||||||
link: string;
|
link: string;
|
||||||
variant?: "sm" | "lg";
|
variant?: "sm" | "lg";
|
||||||
|
image: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// props
|
// props
|
||||||
@@ -45,7 +46,7 @@ const {} = toRefs(props);
|
|||||||
</Tag>
|
</Tag>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
src="/img/hero-bg.jpg"
|
:src="image"
|
||||||
class="absolute size-full object-cover z-10"
|
class="absolute size-full object-cover z-10"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
@@ -104,7 +105,7 @@ const {} = toRefs(props);
|
|||||||
|
|
||||||
<img
|
<img
|
||||||
v-if="variant === 'lg'"
|
v-if="variant === 'lg'"
|
||||||
src="/img/hero-bg.jpg"
|
:src="image"
|
||||||
class="absolute size-full object-cover z-10"
|
class="absolute size-full object-cover z-10"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,48 +23,50 @@ const { colorObject } = useImageColor(`#category-image-${id.value}`);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="relative rounded-150 overflow-hidden w-full h-[500px] bg-white brightness-[97%]">
|
<NuxtLink :to="`/products?category=${id}`">
|
||||||
<img
|
<div class="relative rounded-150 overflow-hidden w-full h-[500px] bg-white brightness-[97%]">
|
||||||
:id="`category-image-${id}`"
|
<img
|
||||||
class="absolute object-contain size-full"
|
:id="`category-image-${id}`"
|
||||||
:src="picture"
|
class="absolute object-contain size-full"
|
||||||
alt=""
|
:src="picture"
|
||||||
/>
|
alt=""
|
||||||
<div
|
/>
|
||||||
v-if="darkLayer"
|
|
||||||
class="bg-linear-to-t from-black/50 to-transparent to-40% absolute z-10 size-full"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="absolute z-20 bottom-0 p-6 flex items-end justify-between w-full"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
:class="
|
v-if="darkLayer"
|
||||||
|
class="bg-linear-to-t from-black/50 to-transparent to-40% absolute z-10 size-full"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="absolute z-20 bottom-0 p-6 flex items-end justify-between w-full"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
:class="
|
||||||
colorObject?.isLight && !darkLayer
|
colorObject?.isLight && !darkLayer
|
||||||
? 'text-black'
|
? 'text-black'
|
||||||
: 'text-white'
|
: 'text-white'
|
||||||
"
|
"
|
||||||
class="flex flex-col gap-2"
|
class="flex flex-col gap-2"
|
||||||
>
|
>
|
||||||
<div class="typo-s-h-md">
|
<div class="typo-s-h-md">
|
||||||
{{ category }}
|
{{ category }}
|
||||||
<span class="typo-p-xs -translate-y-1 inline-block mr-1">
|
<span class="typo-p-xs -translate-y-1 inline-block mr-1">
|
||||||
{{ count }}
|
{{ count }}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
<span class="typo-p-md">محصولات ما را مشاهده کنید</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="typo-p-md">محصولات ما را مشاهده کنید</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
size="24"
|
size="24"
|
||||||
name="ci:arrow-left"
|
name="ci:arrow-left"
|
||||||
class="mb-1"
|
class="mb-1"
|
||||||
:class="
|
:class="
|
||||||
colorObject?.isLight && !darkLayer
|
colorObject?.isLight && !darkLayer
|
||||||
? '**:stroke-black'
|
? '**:stroke-black'
|
||||||
: '**:stroke-white'
|
: '**:stroke-white'
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const onSwiper = (swiper: SwiperClass) => {
|
|||||||
dark-layer
|
dark-layer
|
||||||
:id="slide.id"
|
:id="slide.id"
|
||||||
:category="slide.name"
|
:category="slide.name"
|
||||||
:picture="slide.icon"
|
:picture="slide.image"
|
||||||
:count="slide.product_count"
|
:count="slide.product_count"
|
||||||
description="توضیحات دسته بندی"
|
description="توضیحات دسته بندی"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const {} = toRefs(props);
|
|||||||
<div class="flex gap-12">
|
<div class="flex gap-12">
|
||||||
<div class="flex-1 flex flex-col gap-12">
|
<div class="flex-1 flex flex-col gap-12">
|
||||||
<BlogPost
|
<BlogPost
|
||||||
|
image="/img/blog-1.jpeg"
|
||||||
description="aaasd"
|
description="aaasd"
|
||||||
title="asd"
|
title="asd"
|
||||||
:comments="2"
|
:comments="2"
|
||||||
@@ -32,6 +33,7 @@ const {} = toRefs(props);
|
|||||||
tag="asdsa"
|
tag="asdsa"
|
||||||
/>
|
/>
|
||||||
<BlogPost
|
<BlogPost
|
||||||
|
image="/img/blog-2.jpeg"
|
||||||
description="aaasd"
|
description="aaasd"
|
||||||
title="asd"
|
title="asd"
|
||||||
:comments="2"
|
:comments="2"
|
||||||
@@ -42,6 +44,7 @@ const {} = toRefs(props);
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex-[0.8] flex flex-col">
|
<div class="flex-[0.8] flex flex-col">
|
||||||
<BlogPost
|
<BlogPost
|
||||||
|
image="/img/blog-3.jpeg"
|
||||||
description="aaasd"
|
description="aaasd"
|
||||||
title="asd"
|
title="asd"
|
||||||
:comments="2"
|
:comments="2"
|
||||||
@@ -51,6 +54,7 @@ const {} = toRefs(props);
|
|||||||
variant="sm"
|
variant="sm"
|
||||||
/>
|
/>
|
||||||
<BlogPost
|
<BlogPost
|
||||||
|
image="/img/blog-4.jpeg"
|
||||||
description="aaasd"
|
description="aaasd"
|
||||||
title="asd"
|
title="asd"
|
||||||
:comments="2"
|
:comments="2"
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ const slides = computed(() => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
picture: product.value!.image2
|
picture: product.value?.image2 ?? product.value!.image1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
picture: product.value!.image3
|
picture: product.value!.image3 ?? product.value!.image1
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
@@ -46,9 +46,12 @@ const slides = computed(() => {
|
|||||||
<span class="typo-p-2xl"> {{ product!.price }} </span>
|
<span class="typo-p-2xl"> {{ product!.price }} </span>
|
||||||
<Rating />
|
<Rating />
|
||||||
</div>
|
</div>
|
||||||
<p class="typo-p-md text-slate-500 text-justify">
|
|
||||||
{{ product!.description }}
|
<p
|
||||||
</p>
|
class="py-8 typo-p-md text-slate-500 text-justify [&_a]:text-blue-400 [&_strong]:font-bold [&_u]:text-red-400"
|
||||||
|
v-html="product!.description"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="w-full flex flex-col gap-6 mt-4">
|
<div class="w-full flex flex-col gap-6 mt-4">
|
||||||
<RemainQuantity
|
<RemainQuantity
|
||||||
:maxQuantity="product!.in_stock"
|
:maxQuantity="product!.in_stock"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { API_ENDPOINTS, QUERY_KEYS } from "~/constants";
|
|||||||
// types
|
// types
|
||||||
|
|
||||||
export type GetHomeDataResponse = {
|
export type GetHomeDataResponse = {
|
||||||
"sliders": {
|
"sliders": {
|
||||||
"id": number,
|
"id": number,
|
||||||
"link": string,
|
"link": string,
|
||||||
"title": string,
|
"title": string,
|
||||||
@@ -14,12 +14,7 @@ export type GetHomeDataResponse = {
|
|||||||
"image": string | null,
|
"image": string | null,
|
||||||
"video": string | null
|
"video": string | null
|
||||||
}[],
|
}[],
|
||||||
"sub_categories": {
|
"sub_categories": SubCategory[],
|
||||||
"id": number,
|
|
||||||
"name": string,
|
|
||||||
"icon": string,
|
|
||||||
"product_count": number,
|
|
||||||
}[],
|
|
||||||
"products": Product[],
|
"products": Product[],
|
||||||
"difreance_section": {
|
"difreance_section": {
|
||||||
"image1": string,
|
"image1": string,
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const useGetProducts = (params?: GetProductsFilters) => {
|
|||||||
category: params?.category,
|
category: params?.category,
|
||||||
price_gte: params?.price_gte,
|
price_gte: params?.price_gte,
|
||||||
price_lte: params?.price_lte,
|
price_lte: params?.price_lte,
|
||||||
offest: params?.page! * 9 - 9,
|
offset: params?.page ? Number(params.page) * 9 - 9 : 0,
|
||||||
limit: 9,
|
limit: 9,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-25
@@ -17,11 +17,12 @@ const filteredCategories = computed(() => {
|
|||||||
|
|
||||||
if (debouncedSearch.value.length > 0) {
|
if (debouncedSearch.value.length > 0) {
|
||||||
return categories.value!.map((cat) => {
|
return categories.value!.map((cat) => {
|
||||||
cat.subcategorys = cat.subcategorys.filter((subcat) => {
|
const copyOfCategory = { ...cat };
|
||||||
|
copyOfCategory.subcategorys = copyOfCategory.subcategorys.filter((subcat) => {
|
||||||
return subcat.name.includes(debouncedSearch.value);
|
return subcat.name.includes(debouncedSearch.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return cat;
|
return copyOfCategory;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,32 +67,43 @@ await useAsyncData(async () => {
|
|||||||
</Input>
|
</Input>
|
||||||
</div>
|
</div>
|
||||||
<Transition name="fade" mode="out-in">
|
<Transition name="fade" mode="out-in">
|
||||||
<div v-if="filteredCategories">
|
<div
|
||||||
<div
|
class="flex flex-col gap-20"
|
||||||
class="flex flex-col gap-6"
|
v-if="filteredCategories.some(cat => cat.subcategorys.length > 0)"
|
||||||
v-for="mainCategory in filteredCategories"
|
>
|
||||||
>
|
|
||||||
<div class="w-full flex items-center justify-between">
|
<template v-for="mainCategory in filteredCategories">
|
||||||
<span>
|
|
||||||
{{ mainCategory.name }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-auto-animate
|
class="flex flex-col gap-12"
|
||||||
class="grid grid-cols-3 gap-4 w-full mt-12"
|
v-if="mainCategory.subcategorys.length > 0"
|
||||||
>
|
>
|
||||||
<CategoryCard
|
<div class="w-full flex items-center justify-between gap-8">
|
||||||
v-for="category in mainCategory.subcategorys"
|
<div class="flex items-center gap-2">
|
||||||
:key="category.id"
|
<!-- <img :src="mainCategory.icon" alt="" class="w-[30px] opacity-50" />-->
|
||||||
:id="category.id"
|
<span class="typo-h-5">
|
||||||
:category="category.name"
|
{{ mainCategory.name }}
|
||||||
:picture="category.icon"
|
</span>
|
||||||
:count="20"
|
</div>
|
||||||
description="یک دسته بندی تستasdasd"
|
<div class="h-px w-full bg-slate-200" />
|
||||||
dark-layer
|
</div>
|
||||||
/>
|
<div
|
||||||
|
v-auto-animate
|
||||||
|
class="grid grid-cols-3 gap-4 w-full"
|
||||||
|
>
|
||||||
|
<CategoryCard
|
||||||
|
v-for="category in mainCategory.subcategorys"
|
||||||
|
:key="category.id"
|
||||||
|
:id="category.id"
|
||||||
|
:category="category.name"
|
||||||
|
:picture="category.image"
|
||||||
|
:count="20"
|
||||||
|
description="یک دسته بندی تستasdasd"
|
||||||
|
dark-layer
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="flex w-full mt-12">
|
<div v-else class="flex w-full mt-12">
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ await useAsyncData(async () => {
|
|||||||
<ProductVideo />
|
<ProductVideo />
|
||||||
<ProductComments />
|
<ProductComments />
|
||||||
<ProductDetails />
|
<ProductDetails />
|
||||||
<ProductsSlider title="محصولات مشابه" />
|
<!-- <ProductsSlider title="محصولات مشابه" />-->
|
||||||
<ChatButton />
|
<ChatButton />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 806 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 606 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 917 KiB |
Vendored
+1
@@ -57,6 +57,7 @@ declare global {
|
|||||||
"name": string,
|
"name": string,
|
||||||
"slug": string,
|
"slug": string,
|
||||||
"icon": string,
|
"icon": string,
|
||||||
|
"image" : string,
|
||||||
"product_count": string,
|
"product_count": string,
|
||||||
"parent": string,
|
"parent": string,
|
||||||
"show": boolean
|
"show": boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user