feat: 슬라이드 화살표 클릭 로그 추가 및 관련 로직 개선
This commit is contained in:
@@ -10,12 +10,28 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const {locale} = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const handleLinkClick = (title) => {
|
||||
const trackingData = {
|
||||
tracking: {
|
||||
click_item: title,
|
||||
action_type: 'click',
|
||||
click_sarea: ''
|
||||
}
|
||||
}
|
||||
sendLog(locale.value, useAnalyticsLogDataDirect(trackingData, 1))
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="props.title || props.description"
|
||||
:class="`card-news ${props.class || ''}`"
|
||||
@click="handleLinkClick(props.title)"
|
||||
>
|
||||
<img
|
||||
:src="props.imgPath"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { Splide } from '@splidejs/vue-splide'
|
||||
import type { Splide as SplideType, ResponsiveOptions } from '@splidejs/splide'
|
||||
import type { SlideItemSize } from '#layers/types/components/slide'
|
||||
import { useSplideArrow } from '#layers/composables/useSplideArrow'
|
||||
|
||||
interface Props {
|
||||
slideItemSize: SlideItemSize
|
||||
@@ -20,6 +21,9 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
const emit = defineEmits(['mounted', 'move', 'moved', 'arrowClick'])
|
||||
|
||||
// Splide 화살표 로직을 위한 composable 사용
|
||||
const { addArrowClickListeners } = useSplideArrow()
|
||||
|
||||
const isMultipleItems = computed(() => {
|
||||
return props.slideItemLength > 1
|
||||
})
|
||||
@@ -85,7 +89,9 @@ const handleSplideMounted = (splide: SplideType) => {
|
||||
|
||||
// 화살표 버튼 클릭 이벤트 리스너 추가
|
||||
nextTick(() => {
|
||||
addArrowClickListeners(splide)
|
||||
addArrowClickListeners(splide, (direction, targetIndex) => {
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -107,34 +113,6 @@ const handleMoved = (
|
||||
emit('moved', splide, newIndex, oldIndex, destIndex)
|
||||
}
|
||||
|
||||
const handleArrowClick = (direction: 'prev' | 'next', splide: SplideType) => {
|
||||
const currentIndex = splide.index
|
||||
const totalSlides = splide.length
|
||||
|
||||
// 이동할 슬라이드 인덱스 계산
|
||||
let targetIndex: number
|
||||
if (direction === 'next') {
|
||||
targetIndex = currentIndex + 1 >= totalSlides ? 0 : currentIndex + 1
|
||||
} else {
|
||||
targetIndex = currentIndex - 1 < 0 ? totalSlides - 1 : currentIndex - 1
|
||||
}
|
||||
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
}
|
||||
|
||||
// 화살표 버튼에 클릭 이벤트 리스너 추가
|
||||
const addArrowClickListeners = (splide: SplideType) => {
|
||||
const prevArrow = splide.root.querySelector('.arrow-prev')
|
||||
const nextArrow = splide.root.querySelector('.arrow-next')
|
||||
|
||||
if (prevArrow) {
|
||||
prevArrow.addEventListener('click', () => handleArrowClick('prev', splide))
|
||||
}
|
||||
|
||||
if (nextArrow) {
|
||||
nextArrow.addEventListener('click', () => handleArrowClick('next', splide))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
@@ -18,7 +18,10 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
pagination: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['mounted', 'move', 'moved'])
|
||||
const emit = defineEmits(['mounted', 'move', 'moved', 'arrowClick'])
|
||||
|
||||
// Splide 화살표 로직을 위한 composable 사용
|
||||
const { addArrowClickListeners } = useSplideArrow()
|
||||
|
||||
const isMultipleItems = computed(() => {
|
||||
return props.slideItemLength > 1
|
||||
@@ -85,6 +88,13 @@ const style = computed(() => {
|
||||
const handleSplideMounted = (splide: SplideType) => {
|
||||
emit('mounted', splide)
|
||||
splide.refresh()
|
||||
|
||||
// 화살표 버튼 클릭 이벤트 리스너 추가
|
||||
nextTick(() => {
|
||||
addArrowClickListeners(splide, (direction, targetIndex) => {
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const handleMove = (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Splide } from '@splidejs/vue-splide'
|
||||
import type { Splide as SplideType, ResponsiveOptions } from '@splidejs/splide'
|
||||
import { useSplideArrow } from '#layers/composables/useSplideArrow'
|
||||
|
||||
interface Props {
|
||||
autoplay?: boolean | string
|
||||
@@ -18,6 +19,9 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
|
||||
const emit = defineEmits(['mounted', 'move', 'moved', 'arrowClick'])
|
||||
|
||||
// Splide 화살표 로직을 위한 composable 사용
|
||||
const { addArrowClickListeners } = useSplideArrow()
|
||||
|
||||
const options = computed((): ResponsiveOptions => {
|
||||
return {
|
||||
type: 'fade',
|
||||
@@ -47,7 +51,9 @@ const handleSplideMounted = (splide: SplideType) => {
|
||||
|
||||
// 화살표 버튼 클릭 이벤트 리스너 추가
|
||||
nextTick(() => {
|
||||
addArrowClickListeners(splide)
|
||||
addArrowClickListeners(splide, (direction, targetIndex) => {
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -69,34 +75,6 @@ const handleMoved = (
|
||||
emit('moved', splide, newIndex, oldIndex, destIndex)
|
||||
}
|
||||
|
||||
const handleArrowClick = (direction: 'prev' | 'next', splide: SplideType) => {
|
||||
const currentIndex = splide.index
|
||||
const totalSlides = splide.length
|
||||
|
||||
// 이동할 슬라이드 인덱스 계산
|
||||
let targetIndex: number
|
||||
if (direction === 'next') {
|
||||
targetIndex = currentIndex + 1 >= totalSlides ? 0 : currentIndex + 1
|
||||
} else {
|
||||
targetIndex = currentIndex - 1 < 0 ? totalSlides - 1 : currentIndex - 1
|
||||
}
|
||||
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
}
|
||||
|
||||
// 화살표 버튼에 클릭 이벤트 리스너 추가
|
||||
const addArrowClickListeners = (splide: SplideType) => {
|
||||
const prevArrow = splide.root.querySelector('.arrow-prev')
|
||||
const nextArrow = splide.root.querySelector('.arrow-next')
|
||||
|
||||
if (prevArrow) {
|
||||
prevArrow.addEventListener('click', () => handleArrowClick('prev', splide))
|
||||
}
|
||||
|
||||
if (nextArrow) {
|
||||
nextArrow.addEventListener('click', () => handleArrowClick('next', splide))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
PageDataTemplateComponentSet,
|
||||
PageDataResourceGroup,
|
||||
} from '#layers/types/api/pageData'
|
||||
import { useSplideArrow } from '#layers/composables/useSplideArrow'
|
||||
|
||||
interface Props {
|
||||
slideData: PageDataTemplateComponentSet[]
|
||||
@@ -27,6 +28,9 @@ const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const emit = defineEmits(['arrowClick'])
|
||||
|
||||
// Splide 화살표 로직을 위한 composable 사용
|
||||
const { addArrowClickListeners } = useSplideArrow()
|
||||
|
||||
|
||||
let mainInst: SplideType | null = null
|
||||
let thumbsInst: SplideType | null = null
|
||||
@@ -107,34 +111,6 @@ const stopVideo = () => {
|
||||
playingSlideIndex.value = null
|
||||
}
|
||||
|
||||
const handleArrowClick = (direction: 'prev' | 'next', splide: SplideType) => {
|
||||
const currentIndex = splide.index
|
||||
const totalSlides = splide.length
|
||||
|
||||
// 이동할 슬라이드 인덱스 계산
|
||||
let targetIndex: number
|
||||
if (direction === 'next') {
|
||||
targetIndex = currentIndex + 1 >= totalSlides ? 0 : currentIndex + 1
|
||||
} else {
|
||||
targetIndex = currentIndex - 1 < 0 ? totalSlides - 1 : currentIndex - 1
|
||||
}
|
||||
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
}
|
||||
|
||||
// 화살표 버튼에 클릭 이벤트 리스너 추가
|
||||
const addArrowClickListeners = (splide: SplideType) => {
|
||||
const prevArrow = splide.root.querySelector('.arrow-prev')
|
||||
const nextArrow = splide.root.querySelector('.arrow-next')
|
||||
|
||||
if (prevArrow) {
|
||||
prevArrow.addEventListener('click', () => handleArrowClick('prev', splide))
|
||||
}
|
||||
|
||||
if (nextArrow) {
|
||||
nextArrow.addEventListener('click', () => handleArrowClick('next', splide))
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
mainInst = mainRef.value?.splide ?? null
|
||||
@@ -146,7 +122,9 @@ onMounted(() => {
|
||||
|
||||
// 썸네일 슬라이드의 화살표 버튼에 이벤트 리스너 추가
|
||||
nextTick(() => {
|
||||
addArrowClickListeners(thumbsInst)
|
||||
addArrowClickListeners(thumbsInst, (direction, targetIndex) => {
|
||||
emit('arrowClick', direction, targetIndex)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -5,22 +5,25 @@ const props = defineProps<{
|
||||
resourcesData: PageDataResourceGroup
|
||||
pageVerTmplSeq: number
|
||||
}>()
|
||||
const { useAnalyticsLogDataDirect } = useAnalytics()
|
||||
const logData = useAnalyticsLogDataDirect(props.resourcesData, props.pageVerTmplSeq)
|
||||
|
||||
// YouTube 모달 스토어 사용
|
||||
const modalStore = useModalStore()
|
||||
|
||||
const {locale} = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
|
||||
// 비디오 플레이 버튼 클릭 핸들러
|
||||
const handleVideoPlayClick = () => {
|
||||
const youtubeUrl = props.resourcesData?.display?.text ?? ''
|
||||
modalStore.handleOpenYoutube({ youtubeUrl })
|
||||
|
||||
sendLog(locale.value, useAnalyticsLogDataDirect(props.resourcesData, props.pageVerTmplSeq))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AtomsButtonPlay
|
||||
v-analytics="logData"
|
||||
:resources-data="resourcesData"
|
||||
@click="handleVideoPlayClick"
|
||||
/>
|
||||
|
||||
68
layers/composables/useSplideArrow.ts
Normal file
68
layers/composables/useSplideArrow.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import type { Splide as SplideType } from '@splidejs/splide'
|
||||
|
||||
/**
|
||||
* Splide 슬라이더의 화살표 클릭 로직을 처리하는 composable
|
||||
*/
|
||||
export const useSplideArrow = () => {
|
||||
/**
|
||||
* 화살표 클릭 시 슬라이드 인덱스를 계산하는 함수
|
||||
* @param direction - 이동 방향 ('prev' | 'next')
|
||||
* @param splide - Splide 인스턴스
|
||||
* @returns 다음 슬라이드 인덱스
|
||||
*/
|
||||
const calculateTargetIndex = (direction: 'prev' | 'next', splide: SplideType): number => {
|
||||
const currentIndex = splide.index
|
||||
const totalSlides = splide.length
|
||||
|
||||
if (direction === 'next') {
|
||||
return currentIndex + 1 >= totalSlides ? 0 : currentIndex + 1
|
||||
} else {
|
||||
return currentIndex - 1 < 0 ? totalSlides - 1 : currentIndex - 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 화살표 클릭 핸들러
|
||||
* @param direction - 이동 방향
|
||||
* @param splide - Splide 인스턴스
|
||||
* @param onArrowClick - 화살표 클릭 시 실행될 콜백 함수
|
||||
*/
|
||||
const handleArrowClick = (
|
||||
direction: 'prev' | 'next',
|
||||
splide: SplideType,
|
||||
onArrowClick?: (direction: 'prev' | 'next', targetIndex: number) => void
|
||||
) => {
|
||||
const targetIndex = calculateTargetIndex(direction, splide)
|
||||
|
||||
if (onArrowClick) {
|
||||
onArrowClick(direction, targetIndex)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 화살표 버튼에 클릭 이벤트 리스너를 추가하는 함수
|
||||
* @param splide - Splide 인스턴스
|
||||
* @param onArrowClick - 화살표 클릭 시 실행될 콜백 함수
|
||||
*/
|
||||
const addArrowClickListeners = (
|
||||
splide: SplideType,
|
||||
onArrowClick?: (direction: 'prev' | 'next', targetIndex: number) => void
|
||||
) => {
|
||||
const prevArrow = splide.root.querySelector('.arrow-prev')
|
||||
const nextArrow = splide.root.querySelector('.arrow-next')
|
||||
|
||||
if (prevArrow) {
|
||||
prevArrow.addEventListener('click', () => handleArrowClick('prev', splide, onArrowClick))
|
||||
}
|
||||
|
||||
if (nextArrow) {
|
||||
nextArrow.addEventListener('click', () => handleArrowClick('next', splide, onArrowClick))
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
calculateTargetIndex,
|
||||
handleArrowClick,
|
||||
addArrowClickListeners
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,12 @@ const handleChange = (
|
||||
'buttonList'
|
||||
)
|
||||
}
|
||||
const {locale} = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
const onArrowClick = (direction, targetIndex) => {
|
||||
const logTraking = direction == 'prev' ? props.components.arrow.groups[0] : props.components.arrow.groups[1];
|
||||
sendLog(locale.value, useAnalyticsLogDataDirect(logTraking, 1))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -78,6 +84,7 @@ const handleChange = (
|
||||
:pagination="false"
|
||||
class="mt-[24px] md:mt-[48px]"
|
||||
@move="handleChange"
|
||||
@arrow-click="onArrowClick"
|
||||
>
|
||||
<SplideSlide v-for="(item, index) in slideData" :key="index">
|
||||
<div class="slide-inner border-line">
|
||||
|
||||
@@ -71,6 +71,14 @@ const slideItemSize = {
|
||||
gap: 32,
|
||||
},
|
||||
}
|
||||
const {locale} = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
const onArrowClick = (direction, targetIndex) => {
|
||||
const logTraking = direction == 'prev' ? props.components.arrow.groups[0] : props.components.arrow.groups[1];
|
||||
sendLog(locale.value, useAnalyticsLogDataDirect(logTraking, 1))
|
||||
}
|
||||
|
||||
console.log('resourcesData.value===', resourcesData.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -96,6 +104,7 @@ const slideItemSize = {
|
||||
:resources-data="videoPlayData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
/>
|
||||
|
||||
<WidgetsButtonList
|
||||
v-if="buttonListData.length > 0"
|
||||
:resources-data="buttonListData"
|
||||
@@ -108,6 +117,7 @@ const slideItemSize = {
|
||||
:slide-item-length="slideData?.length"
|
||||
:pagination="false"
|
||||
class="mt-[36px] md:mt-[60px]"
|
||||
@arrow-click="onArrowClick"
|
||||
>
|
||||
<SplideSlide v-for="(item, index) in slideData" :key="index">
|
||||
<BlocksCardNews
|
||||
|
||||
Reference in New Issue
Block a user