merge and add list texts for detail model

This commit is contained in:
Parsa Nazer
2025-04-24 21:55:23 +03:30
6 changed files with 132 additions and 117 deletions
@@ -45,106 +45,111 @@ const emptySlidesCount = computed(() => {
const changeSlide = (id: number) => {
emit("update:selectedSlide", id);
};
</script>
<template>
<div class="flex flex-col relative gap-6">
<div
class="bg-white brightness-[97%] w-full relative aspect-square overflow-hidden rounded-[12px] md:rounded-200"
>
<Transition name="zoom" mode="out-in">
<NuxtImg
:key="selectedSlideDetail.id"
class="size-full absolute object-contain"
:src="selectedSlideDetail.image"
:alt="selectedSlideDetail.name"
/>
</Transition>
</div>
<div class="relative w-full">
<Swiper
:slides-per-view="3"
:space-between="20"
@swiper="onSwiper"
class="w-full"
<div class="sticky top-10">
<div class="flex flex-col relative gap-6">
<div
class="bg-white brightness-[97%] w-full relative aspect-square overflow-hidden rounded-[12px] md:rounded-200"
>
<SwiperSlide
class="py-4"
v-for="slide in slides"
:key="slide.id"
<Transition
name="zoom"
mode="out-in"
>
<div
@click="changeSlide(slide.id)"
:class="
selectedSlide === slide.id
? '!border-black'
: 'border-transparent'
"
class="active:scale-95 hover:border-slate-200 transition-all cursor-pointer brightness-[97%] bg-white aspect-square border-2 rounded-[12px] md:rounded-200 w-full overflow-hidden relative"
<NuxtImg
:key="selectedSlideDetail.id"
class="size-full absolute object-contain"
:src="selectedSlideDetail.image"
:alt="selectedSlideDetail.name"
/>
</Transition>
</div>
<div class="relative w-full">
<Swiper
:slides-per-view="3"
:space-between="20"
@swiper="onSwiper"
class="w-full"
>
<SwiperSlide
class="py-4"
v-for="slide in slides"
:key="slide.id"
>
<NuxtImg
class="absolute object-cover size-full"
:src="slide.image"
:alt="String(slide.id)"
/>
</div>
</SwiperSlide>
<SwiperSlide
v-if="emptySlidesCount > 0"
v-for="slide in emptySlidesCount"
:key="slide"
class="py-4"
<div
@click="changeSlide(slide.id)"
:class="selectedSlide === slide.id ? '!border-black' : 'border-transparent'"
class="active:scale-95 hover:border-slate-200 transition-all cursor-pointer brightness-[97%] bg-white aspect-square border-2 rounded-[12px] md:rounded-200 w-full overflow-hidden relative"
>
<NuxtImg
class="absolute object-cover size-full"
:src="slide.image"
:alt="String(slide.id)"
/>
</div>
</SwiperSlide>
<SwiperSlide
v-if="emptySlidesCount > 0"
v-for="slide in emptySlidesCount"
:key="slide"
class="py-4"
>
<div
class="brightness-[97%] flex-center bg-white aspect-square rounded-[12px] md:rounded-200 w-full"
>
<Icon
name="ci:image-slash"
class="size-[40px] sm:size-[60px] **:fill-black/20"
/>
</div>
</SwiperSlide>
</Swiper>
<div
v-if="slides.length > 3"
@click="swiper_instance?.slidePrev()"
class="absolute z-20 -right-4 shadow-lg cursor-pointer shadow-black/10 bottom-[50%] translate-y-1/2 bg-white rounded-full size-10 xs:size-11.5 flex justify-center items-center"
>
<div class="brightness-[97%] flex-center bg-white aspect-square rounded-[12px] md:rounded-200 w-full">
<Icon name="ci:image-slash" class="size-[40px] sm:size-[60px] **:fill-black/20" />
</div>
</SwiperSlide>
</Swiper>
<Icon
name="ci:arrow-right"
class="**:stroke-black size-5 xs:size-6"
:class="swiper_instance?.isBeginning ? '**:stroke-black/30' : ''"
/>
</div>
<div
v-if="slides.length > 3"
@click="swiper_instance?.slidePrev()"
class="absolute z-20 -right-4 shadow-lg cursor-pointer shadow-black/10 bottom-[50%] translate-y-1/2 bg-white rounded-full size-10 xs:size-11.5 flex justify-center items-center"
>
<Icon
name="ci:arrow-right"
class="**:stroke-black size-5 xs:size-6"
:class="swiper_instance?.isBeginning ? '**:stroke-black/30' : ''"
/>
</div>
<div
v-if="slides.length > 3"
@click="swiper_instance?.slideNext()"
class="absolute z-20 -left-4 shadow-lg cursor-pointer shadow-black/10 bottom-[50%] translate-y-1/2 bg-white rounded-full size-10 xs:size-11.5 flex justify-center items-center"
>
<Icon
name="ci:arrow-left"
class="**:stroke-black size-5 xs:size-6"
:class="swiper_instance?.isEnd ? '**:stroke-black/30' : ''"
/>
<div
v-if="slides.length > 3"
@click="swiper_instance?.slideNext()"
class="absolute z-20 -left-4 shadow-lg cursor-pointer shadow-black/10 bottom-[50%] translate-y-1/2 bg-white rounded-full size-10 xs:size-11.5 flex justify-center items-center"
>
<Icon
name="ci:arrow-left"
class="**:stroke-black size-5 xs:size-6"
:class="swiper_instance?.isEnd ? '**:stroke-black/30' : ''"
/>
</div>
</div>
<!-- <div class="grid grid-cols-3 gap-6">-->
<!-- <div-->
<!-- @click="changeSlide(slide.id)"-->
<!-- v-for="slide in slides"-->
<!-- :class="-->
<!-- selectedSlide === slide.id-->
<!-- ? '!ring-black'-->
<!-- : 'ring-transparent'-->
<!-- "-->
<!-- class="active:scale-95 hover:ring-slate-200 transition-all cursor-pointer brightness-[97%] bg-white aspect-square ring-2 ring-offset-4 rounded-[12px] md:rounded-200 w-full overflow-hidden relative"-->
<!-- :key="slide.id"-->
<!-- >-->
<!-- <img-->
<!-- class="absolute object-cover size-full"-->
<!-- :src="slide.image"-->
<!-- :alt="String(slide.id)"-->
<!-- />-->
<!-- </div>-->
<!-- </div>-->
</div>
<!-- <div class="grid grid-cols-3 gap-6">-->
<!-- <div-->
<!-- @click="changeSlide(slide.id)"-->
<!-- v-for="slide in slides"-->
<!-- :class="-->
<!-- selectedSlide === slide.id-->
<!-- ? '!ring-black'-->
<!-- : 'ring-transparent'-->
<!-- "-->
<!-- class="active:scale-95 hover:ring-slate-200 transition-all cursor-pointer brightness-[97%] bg-white aspect-square ring-2 ring-offset-4 rounded-[12px] md:rounded-200 w-full overflow-hidden relative"-->
<!-- :key="slide.id"-->
<!-- >-->
<!-- <img-->
<!-- class="absolute object-cover size-full"-->
<!-- :src="slide.image"-->
<!-- :alt="String(slide.id)"-->
<!-- />-->
<!-- </div>-->
<!-- </div>-->
</div>
</template>
@@ -1,11 +1,9 @@
<script lang="ts" setup>
import type { ProductVariantProvideType } from '~/pages/product/[id].vue';
import type { ProductVariantProvideType } from "~/pages/product/[id].vue";
// provide / inject
const { selectedVariant } = inject("productVariant") as ProductVariantProvideType;
</script>
<template>
@@ -21,9 +19,7 @@ const { selectedVariant } = inject("productVariant") as ProductVariantProvideTyp
:value="'item' + detailItem.detail_category"
class="overflow-hidden"
>
<AccordionHeader
class="border-t border-slate-200 py-[1.5rem] flex justify-between items-center"
>
<AccordionHeader class="border-t border-slate-200 py-[1.5rem] flex justify-between items-center">
<span class="typo-sub-h-md text-black">{{ detailItem.detail_category }}</span>
<AccordionTrigger class="group">
<Icon
@@ -36,21 +32,22 @@ const { selectedVariant } = inject("productVariant") as ProductVariantProvideTyp
<AccordionContent
class="data-[state=open]:animate-slide-down pb-[1.5rem] data-[state=closed]:animate-slide-up overflow-hidden"
>
<div
class="w-full grid grid-cols-2 gap-y-[1.5rem] gap-x-[1rem]"
>
<div class="w-full grid grid-cols-2 gap-y-[1.5rem] gap-x-[1rem]">
<div
v-for="item in detailItem.detail"
v-for="item in detailItem.details"
class="flex flex-col gap-y-[1.5rem]"
>
<span
class="typo-sub-h-lg text-black w-full pt-[1.5rem]"
>
<span class="typo-sub-h-lg text-black w-full pt-[1.5rem]">
{{ item.title }}
</span>
<ul class="list-disc w-full ps-5">
<li
v-for="detail in [ item.detail_text1, item.detail_text2, item.detail_text3, item.detail_text4 ]"
v-for="detail in [
item.detail_text1,
item.detail_text2,
item.detail_text3,
item.detail_text4,
]"
class="text-slate-500 typo-p-md"
>
{{ detail }}
@@ -62,4 +59,4 @@ const { selectedVariant } = inject("productVariant") as ProductVariantProvideTyp
</AccordionItem>
</AccordionRoot>
</div>
</template>
</template>
+1 -1
View File
@@ -28,7 +28,7 @@ const onSwiper = (swiper: SwiperClass) => {
<div class="w-full mt-44 lg:mt-64 relative">
<NuxtImg
class="aspect-square w-[240px] md:w-[300px] lg:w-[350px] translate-y-[-164px] md:translate-y-[-206px] lg:translate-y-[-240px] absolute left-1/2 -translate-x-1/2 z-10"
class="aspect-square w-[210px] sm:w-[240px] md:w-[300px] lg:w-[350px] translate-y-[-164px] md:translate-y-[-206px] lg:translate-y-[-240px] absolute left-1/2 -translate-x-1/2 z-10"
:style="{
filter: 'drop-shadow(0px 0px 20px rgba(0, 0, 0, 0.4))',
}"
+2 -2
View File
@@ -242,9 +242,9 @@ onUnmounted(() => {
/>
</button>
</div>
<h3 class="typo-h-6 md:typo-h-4 lg:typo-h-1 tracking-[-2px] text-white">
<NuxtLink :to="slide.link" class="typo-h-6 md:typo-h-4 lg:typo-h-1 tracking-[-2px] text-white">
{{ slide.title }}
</h3>
</NuxtLink>
</div>
<div class="flex justify-between items-center">
<span class="truncate typo-p-xs md:typo-p-sm lg:typo-p-lg text-white">
@@ -10,7 +10,7 @@ import { useAuth } from "~/composables/api/auth/useAuth";
// provide-inject
const { isOpen } = inject("isOpen") as any;
const { isOpen, closeChat } = inject("isOpen") as any;
// state
@@ -128,7 +128,7 @@ whenever(
<Transition :name="isMobile ? 'fade-down' : 'fade-right-to-left'">
<div
v-if="isOpen"
class="fixed z-50 max-xs:inset-0 xs:right-8 xs:bottom-8 w-full xs:w-[450px] transition-all duration-500 overflow-hidden h-svh xs:h-[700px] xs:rounded-250 shadow-2xl shadow-black/30 pt-[40px] bg-white"
class="fixed z-9999 max-xs:inset-0 xs:right-8 xs:bottom-8 w-full xs:w-[450px] transition-all duration-500 overflow-hidden h-svh xs:h-[700px] xs:rounded-250 shadow-2xl shadow-black/30 pt-[40px] bg-white"
>
<CloseButton :disabled="!!isCreateMessagePending" />
@@ -185,7 +185,7 @@ whenever(
class="w-full h-full flex items-center justify-center absolute inset-0"
>
<NuxtImg
class="size-[250px] drop-shadow-2xl"
class="size-[225px] sm:size-[250px] drop-shadow-2xl"
src="/img/heymlz/heymlz-small-idle.gif"
alt=""
/>
@@ -197,7 +197,7 @@ whenever(
v-else
>
<NuxtImg
class="size-[250px] drop-shadow-2xl"
class="size-[225px] sm:size-[250px] drop-shadow-2xl"
src="/img/heymlz/heymlz-small-idle.gif"
alt=""
/>
@@ -207,9 +207,22 @@ whenever(
من میتونم هر سوالی رو درمورد این محصول جواب بدم اگه میخوای شروع کنیم روی دکمه زیر کلیک کن
</p>
</div>
<NuxtLink to="/signin">
<Button class="mt-8 rounded-full px-10">ورود به فروشگاه</Button>
</NuxtLink>
<div class="flex-center gap-4">
<Button
@click="closeChat"
class="mt-8 rounded-full px-10"
>
بستن
</Button>
<NuxtLink to="/signin">
<Button
variant="outlined"
class="mt-8 rounded-full px-10"
>
ورود به فروشگاه
</Button>
</NuxtLink>
</div>
</div>
</div>
</Transition>
+1 -1
View File
@@ -70,7 +70,7 @@ declare global {
type ProductDetail = {
id: number;
detail: ProductDetailItem[];
details: ProductDetailItem[];
detail_category: number;
};