Files
tehran_tala/apps/user-app-v2/src/components/slider/Slider.vue
T
s.esmaeili 53a304b5d5 SearchView: Removed the dynamic collection-tile grid (e.g. "پرفروش‌های این هفته") and the "نتایج / N محصول" section header from the UI. Underlying data/filtering logic untouched.
DashboardView ("میز کار"): Rebuilt from scratch with a new structure, distinct from the old card+grid layout but visually aligned with HomeView (same blurred bar, @ink/@wine palette, staged reveal animation on mount):

Single hero card (ink→wine gradient) showing balance, gold/fiat debt, and identity — no quick-action icons inside it anymore.

Live gold rate folded into a slim inline row at the bottom instead of a titled section.
Iterated shadow/spacing on the hero card per feedback (softer, less clipped).
DialogVant / DialogVantOneButton (shared modal components, used in 7+ call sites: Dashboard, Cart, SingleProduct, Register, App): Replaced Vant's default dialog chrome with the app's own rounded-card language — circular icon badge for the illustration, pill-shaped primary/secondary buttons. No call-site markup changed.

LoginView: Rebuilt from scratch — full-bleed dark hero (brand + step copy) overlapped by a floating white form sheet, animated crossfade transition between the mobile-number and OTP steps, same staged entrance animation as Home/Dashboard. All auth logic (API check, OTP stub, session login) unchanged.
2026-09-18 12:54:45 +03:30

140 lines
5.1 KiB
Vue

<!--
Ported from legacy henza_pwa/src/components/slider/slider.vue.
EXISTING ISSUE, ported as-is (not fixed): `showPopup` takes (src, index) but
the template calls it with a single argument (`showPopup(item)`), and the
v-for doesn't even destructure an index. `index` is therefore always
undefined inside showPopup, so its "rotate the slides array to start at the
tapped image" logic never runs — tapping any thumbnail always opens the
full-screen zoom viewer starting from the first image, never the tapped one.
-->
<template>
<div>
<Swiper :grabCursor="true" :centeredSlides="true" :loop="false" :slidesPerView="1" class="w-full slider" :pagination="{ clickable: true }">
<SwiperSlide class="bg-center bg-cover h-auto" v-for="item in slides" :key="item">
<img @click="showPopup(item)" v-lazy="item" class="block w-auto object-cover z-0 pb-1" :style="`height:${height}`" />
</SwiperSlide>
<transition name="slideUp" mode="out-in">
<svg alt="منتزر" class="absolute bottom-0 z-[2] m-auto pointer-events-none w-full h-[90px]" v-if="flagSvg">
<path fill="#FFFFFF" class="w-full h-[90px]" :d="whiteShape" />
<path fill="#3E5279" class="w-full h-[90px]" :d="curvedShape" />
</svg>
</transition>
</Swiper>
<Drawer v-model:visible="show" placement="bottom" :closable="false" :bodyStyle="{ padding: 0 }" class="rtl whitespace-pre-wrap bg-white" height="100vh">
<div @click="show = false" class="fixed top-[30px] right-[20px] z-[5] pb-2 pl-5">
<Icon icon="vuesax-linear:arrow-right-1" @click="show = false" class="cursor-pointer text-white bg-secondary rounded-[5px] p-[2.5px]" size="28" />
</div>
<Swiper :grabCursor="true" :zoom="{ maxRatio: 1.2 }" :modules="[Zoom]" :centeredSlides="true" :loop="false" :slidesPerView="1" class="w-full slider" :key="show">
<SwiperSlide class="bg-center bg-cover h-auto" v-for="item in slides" :key="item">
<div class="swiper-zoom-container">
<img v-lazy="item" class="block object-contain w-[100vw] h-screen" />
</div>
</SwiperSlide>
</Swiper>
</Drawer>
</div>
</template>
<script setup lang="ts">
import { computed, onBeforeMount, ref } from 'vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'
import 'swiper/css/navigation'
import 'swiper/css/pagination'
import 'swiper/css/scrollbar'
import 'swiper/css/zoom'
import SwiperCore, { Navigation, Pagination, Zoom } from 'swiper'
import { Drawer } from 'ant-design-vue'
import Icon from '../icon/Icon.vue'
import { useWindowDataStore } from '../../stores/windowDataStore'
SwiperCore.use([Pagination, Navigation])
const props = withDefaults(defineProps<{ slides: string[]; height: string; width?: string }>(), {})
const show = ref(false)
const slides = ref<string[]>([...props.slides])
const showPopup = (src: string, index?: number) => {
slides.value = [...props.slides]
for (let i = 0; i < (index ?? 0); i++) {
const helper = slides.value.shift()
if (helper) slides.value.push(helper)
}
show.value = true
}
const flagSvg = ref(false)
onBeforeMount(() => {
setTimeout(() => {
flagSvg.value = true
}, 100)
})
const windowData = useWindowDataStore()
const shapeHeight = 90
const wcp1x = computed(() => Math.min(windowData.width, 768) - Math.min(windowData.width, 768) / 21.8878249)
const wcp2x = computed(() => Math.min(windowData.width, 768) - Math.min(windowData.width, 768) / 2.37406336)
const crcr1cp1x = computed(() => Math.min(windowData.width, 768) - Math.min(windowData.width, 768) / 1.56947374)
const crcr1cp2x = computed(() => Math.min(windowData.width, 768) - Math.min(windowData.width, 768) / 5.47609844)
const crcr2cp1x = computed(() => Math.min(windowData.width, 768) - Math.min(windowData.width, 768) / 15.8024691)
const crcr2cp2x = computed(() => Math.min(windowData.width, 768) - Math.min(windowData.width, 768) / 2.2606383)
const whiteShape = computed(() => `M0,${shapeHeight}H${Math.min(windowData.width, 768)}V0C${wcp1x.value},19.17,${wcp2x.value},119.08,0,49Z`)
const curvedShape = computed(
() => `M0,39.77C${crcr1cp1x.value},91.74,${crcr1cp2x.value},61.5,${Math.min(windowData.width, 768)},0,C${crcr2cp1x.value},29.34,${crcr2cp2x.value},112.54,0,57.1Z`,
)
</script>
<style lang="less">
.slider {
.swiper-pagination-bullet {
transition: all 0.2s;
width: 6px;
height: 6px;
}
.swiper-pagination-bullet-active,
.swiper-pagination-bullet-active-main {
width: 24px;
border-radius: 10px;
}
.swiper-horizontal > .swiper-pagination-bullets,
.swiper-pagination-bullets.swiper-pagination-horizontal,
.swiper-pagination-custom,
.swiper-pagination-fraction {
bottom: 40px !important;
}
.swiper-pagination-bullets-dynamic * {
transform: unset !important;
}
.swiper-pagination-bullet-active {
background: @primary;
}
.swiper-slide img {
margin: auto;
}
}
.slideUp-enter-active,
.slideUp-leave-active {
opacity: 1;
transition: all @transition-duration ease @transition-delay;
}
.slideUp-enter-from {
opacity: 0;
transform: translateY(100%);
}
.slideUp-leave-to {
opacity: 0;
transform: translateY(-100%);
}
</style>