Files
web-temp/layers/templates/GrDetail01/index.vue

172 lines
4.7 KiB
Vue

<script setup lang="ts">
import { SplideSlide } from '@splidejs/vue-splide'
import {
getComponentContainer,
getComponentGroupAry,
} from '#layers/utils/dataUtil'
import type { Splide as SplideType } from '@splidejs/splide'
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
interface Props {
components: PageDataTemplateComponents
pageVerTmplSeq: number
}
const props = defineProps<Props>()
const splideRef = ref<SplideSlide | null>(null)
const currentSlideIndex = ref<number | null>(null)
const slideData = computed(() => {
return getComponentContainer(props.components, 'group_sets', { maxLength: 5 })
})
const paginationData = computed(() => {
return getComponentGroupAry(props.components, 'pagination')
})
const goToSlide = (index: number) => {
const splide = splideRef.value?.splide
if (splide) {
splide.go(index)
}
}
const handleSplideMounted = (splide: SplideType) => {
currentSlideIndex.value = splide.index
}
const handleSplideMove = (_splide: SplideType, newIndex: number) => {
currentSlideIndex.value = newIndex
}
</script>
<template>
<section class="section-standard">
<BlocksSlideFade
v-if="slideData"
ref="splideRef"
:autoplay="true"
:arrows="false"
:pagination="false"
class="h-full"
@move="handleSplideMove"
@mounted="handleSplideMounted"
>
<SplideSlide v-for="(item, index) in slideData" :key="index">
<WidgetsBackground
v-if="hasComponentGroup(item, 'background')"
:resources-data="getComponentGroup(item, 'background')"
/>
<div class="content-standard">
<WidgetsMainTitle
v-if="hasComponentGroup(item, 'mainTitle')"
:resources-data="getComponentGroup(item, 'mainTitle')"
class="title-lg max-w-[944px]"
/>
<WidgetsSubTitle
v-if="hasComponentGroup(item, 'subTitle')"
:resources-data="getComponentGroup(item, 'subTitle')"
class="title-md max-w-[944px] mt-0.5 line-clamp-3 md:mt-1 md:line-clamp-2"
/>
<WidgetsDescription
v-if="hasComponentGroup(item, 'description')"
:resources-data="getComponentGroup(item, 'description')"
class="max-w-[944px] mt-4 md:mt-6"
/>
</div>
</SplideSlide>
</BlocksSlideFade>
<div
v-if="slideData && slideData.length > 1"
class="splide-pagination"
:style="getPaginationClass(paginationData)"
>
<div
v-for="(item, index) in slideData"
:key="index"
:class="[
'pagination-item',
{
'is-active': currentSlideIndex === index,
'is-completed': index < currentSlideIndex,
},
]"
>
<button
:class="[
'btn-pagination',
{ 'is-active': currentSlideIndex === index },
]"
@click="goToSlide(index)"
>
<span class="item-bullet"></span>
<span class="item-title">
{{ getComponentGroup(item, 'pagenaviTitle')?.display?.text || '' }}
</span>
</button>
<div v-if="index !== slideData.length - 1" class="progress-bar">
<span class="progress-fill"></span>
</div>
</div>
</div>
</section>
</template>
<style scoped>
.splide-pagination {
@apply flex items-center absolute bottom-10 left-1/2 -translate-x-1/2 z-[5] md:bottom-[96px];
}
.btn-pagination {
@apply relative;
}
.pagination-item {
@apply flex items-center;
}
.item-bullet {
@apply block w-3 h-3 rounded-full transition-[background] duration-300 ease-in-out;
background-color: var(--pagination-disabled);
}
.item-title {
@apply hidden absolute -bottom-[46px] left-1/2 max-w-[184px] line-clamp-1 text-ellipsis whitespace-nowrap text-sm font-medium -translate-x-1/2 transition-[color] duration-300 ease-in-out md:block;
color: var(--pagination-disabled);
}
.progress-bar {
@apply relative w-[68px] h-[1px] overflow-hidden md:w-[184px];
background-color: var(--pagination-disabled);
}
.progress-fill {
@apply absolute inset-y-0 left-0 w-[0];
background-color: var(--pagination-active);
}
/* 활성화 상태 (현재 슬라이드) */
.btn-pagination:hover .item-bullet,
.is-active .item-bullet {
background-color: var(--pagination-active);
}
.btn-pagination:hover .item-title,
.is-active .item-title {
color: var(--pagination-active);
}
.is-active .progress-fill {
animation: progressFill 5000ms linear forwards;
}
/* 완료 상태 (지나간 슬라이드) */
.is-completed .item-bullet {
background-color: var(--pagination-active);
}
.is-completed .progress-fill {
width: 100%;
}
@keyframes progressFill {
from {
width: 0%;
}
to {
width: 100%;
}
}
</style>