fix. 컴포넌트 dataUtil 통일
This commit is contained in:
@@ -10,28 +10,25 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const {locale} = useI18n()
|
||||
const { locale } = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const handleLinkClick = (title) => {
|
||||
const handleLinkClick = (title: string) => {
|
||||
const trackingData = {
|
||||
tracking: {
|
||||
click_item: title,
|
||||
action_type: 'click',
|
||||
click_sarea: ''
|
||||
}
|
||||
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"
|
||||
@@ -52,6 +49,7 @@ const handleLinkClick = (title) => {
|
||||
:href="props.url"
|
||||
:target="props.linkTarget"
|
||||
class="card-link"
|
||||
@click="handleLinkClick(props.title)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -34,7 +34,7 @@ const options = computed((): ResponsiveOptions => {
|
||||
focus: 'center',
|
||||
autoWidth: true,
|
||||
autoHeight: true,
|
||||
speed: 400,
|
||||
speed: 500,
|
||||
updateOnMove: true,
|
||||
arrows: props.arrows && isMultipleItems.value,
|
||||
pagination: props.pagination && isMultipleItems.value,
|
||||
@@ -86,7 +86,7 @@ const style = computed(() => {
|
||||
const handleSplideMounted = (splide: SplideType) => {
|
||||
emit('mounted', splide)
|
||||
splide.refresh()
|
||||
|
||||
|
||||
// 화살표 버튼 클릭 이벤트 리스너 추가
|
||||
nextTick(() => {
|
||||
addArrowClickListeners(splide, (direction, targetIndex) => {
|
||||
@@ -103,18 +103,6 @@ const handleMove = (
|
||||
) => {
|
||||
emit('move', splide, newIndex, oldIndex, destIndex)
|
||||
}
|
||||
|
||||
const handleMoved = (
|
||||
splide: SplideType,
|
||||
newIndex: number,
|
||||
oldIndex: number,
|
||||
destIndex: number
|
||||
) => {
|
||||
emit('moved', splide, newIndex, oldIndex, destIndex)
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -123,7 +111,6 @@ const handleMoved = (
|
||||
:options="options"
|
||||
@splide:mounted="handleSplideMounted"
|
||||
@splide:move="handleMove"
|
||||
@splide:moved="handleMoved"
|
||||
>
|
||||
<slot />
|
||||
</Splide>
|
||||
|
||||
@@ -33,7 +33,7 @@ const options = computed((): ResponsiveOptions => {
|
||||
focus: 'center',
|
||||
autoWidth: true,
|
||||
autoHeight: true,
|
||||
speed: 400,
|
||||
speed: 500,
|
||||
updateOnMove: true,
|
||||
arrows: props.arrows && isMultipleItems.value,
|
||||
pagination: props.pagination && isMultipleItems.value,
|
||||
@@ -88,7 +88,7 @@ const style = computed(() => {
|
||||
const handleSplideMounted = (splide: SplideType) => {
|
||||
emit('mounted', splide)
|
||||
splide.refresh()
|
||||
|
||||
|
||||
// 화살표 버튼 클릭 이벤트 리스너 추가
|
||||
nextTick(() => {
|
||||
addArrowClickListeners(splide, (direction, targetIndex) => {
|
||||
|
||||
@@ -28,7 +28,7 @@ const options = computed((): ResponsiveOptions => {
|
||||
rewind: true,
|
||||
perPage: 1,
|
||||
perMove: 1,
|
||||
speed: 600,
|
||||
speed: 500,
|
||||
updateOnMove: true,
|
||||
autoplay: props.autoplay,
|
||||
pauseOnHover: false,
|
||||
|
||||
@@ -42,7 +42,7 @@ const mainOptions = computed<Options>(() => ({
|
||||
rewind: true,
|
||||
perPage: 1,
|
||||
perMove: 1,
|
||||
speed: 600,
|
||||
speed: 500,
|
||||
arrows: false,
|
||||
pagination: false,
|
||||
drag: props.drag,
|
||||
|
||||
@@ -13,6 +13,9 @@ interface ButtonListProps {
|
||||
const props = defineProps<ButtonListProps>()
|
||||
|
||||
const { gameData } = useGameDataStore()
|
||||
const { locale } = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const BUTTON_TYPE_MAP = {
|
||||
URL: {
|
||||
_self: 'internal' as const,
|
||||
@@ -54,11 +57,14 @@ const getButtonBackgroundImage = (
|
||||
return ''
|
||||
}
|
||||
|
||||
const { locale } = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const handleButtonClick = (btnInfo: PageDataResourceGroupBtnInfo, index: any) => {
|
||||
sendLog(locale.value, useAnalyticsLogDataDirect(props.resourcesData[index], props.pageVerTmplSeq))
|
||||
const handleButtonClick = (
|
||||
btnInfo: PageDataResourceGroupBtnInfo,
|
||||
index: any
|
||||
) => {
|
||||
sendLog(
|
||||
locale.value,
|
||||
useAnalyticsLogDataDirect(props.resourcesData[index], props.pageVerTmplSeq)
|
||||
)
|
||||
|
||||
const marketType = btnInfo?.detail?.market_type
|
||||
if (marketType) {
|
||||
@@ -100,7 +106,7 @@ const handleButtonClick = (btnInfo: PageDataResourceGroupBtnInfo, index: any) =>
|
||||
}"
|
||||
@click="handleButtonClick(button.btn_info, index)"
|
||||
>
|
||||
{{ button.btn_info?.txt_btn_name }}
|
||||
{{ button.btn_info?.txt_btn_name }}
|
||||
</AtomsButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,19 +6,19 @@ const props = defineProps<{
|
||||
pageVerTmplSeq: number
|
||||
}>()
|
||||
|
||||
// YouTube 모달 스토어 사용
|
||||
const modalStore = useModalStore()
|
||||
|
||||
const {locale} = useI18n()
|
||||
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))
|
||||
sendLog(
|
||||
locale.value,
|
||||
useAnalyticsLogDataDirect(props.resourcesData, props.pageVerTmplSeq)
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import * as amplitude from '@amplitude/analytics-browser'
|
||||
import type {
|
||||
AnalyticsDetailType,
|
||||
} from '../types/AnalyticsType'
|
||||
import type { PageDataResourceGroup } from '#layers/types/api/pageData'
|
||||
import type { IdentityInfo, ActionInfo, MarketingInfo } from '../types/Stove'
|
||||
import type { AnalyticsDetailType } from '#layers/types/AnalyticsType'
|
||||
import type {
|
||||
IdentityInfo,
|
||||
ActionInfo,
|
||||
MarketingInfo,
|
||||
} from '#layers/types/Stove'
|
||||
|
||||
declare const svcLog: any
|
||||
declare const twq: any
|
||||
@@ -72,20 +74,20 @@ export const useAnalyticsLogDataDirect = (
|
||||
// logSourceType:pageDataTrack.logSourceType,
|
||||
// viewArea:pageDataTrack.viewArea,
|
||||
// viewType:pageDataTrack.viewType,
|
||||
clickArea:pageData.page_name_en,
|
||||
clickArea: pageData.page_name_en,
|
||||
clickSarea: pageData.templates[pageVerTmplSeq].page_ver_tmpl_name_en,
|
||||
clickItem: `${pageData.templates[pageVerTmplSeq].page_ver_tmpl_name}_${pageDataTrack?.click_item}`,
|
||||
event: pageData.page_name,
|
||||
eventCategory: `${pageData.page_name}_${pageDataTrack?.click_item}`,
|
||||
template_code: pageData.templates[pageVerTmplSeq].template_code,
|
||||
page_ver_tmpl_name: pageData.templates[pageVerTmplSeq].page_ver_tmpl_name,
|
||||
page_ver_tmpl_name_en: pageData.templates[pageVerTmplSeq].page_ver_tmpl_name_en,
|
||||
page_ver_tmpl_name_en:
|
||||
pageData.templates[pageVerTmplSeq].page_ver_tmpl_name_en,
|
||||
} as unknown as AnalyticsDetailType
|
||||
|
||||
return logData
|
||||
}
|
||||
|
||||
|
||||
// target에 {XX1, XX2}와 같은 형태가 포함되어 있을 경우 options.clickItem으로부터 값 추출하여 세팅
|
||||
const findValueFromOption = (target: string, { options = {} }: any) => {
|
||||
if (target.includes('{') && target.includes('}')) {
|
||||
@@ -362,5 +364,12 @@ const sendMarketingScript = ({
|
||||
}
|
||||
|
||||
export default () => {
|
||||
return { sendGA, sendSA, sendLog, sendMarketingScript, useAnalyticsLogData, useAnalyticsLogDataDirect }
|
||||
return {
|
||||
sendGA,
|
||||
sendSA,
|
||||
sendLog,
|
||||
sendMarketingScript,
|
||||
useAnalyticsLogData,
|
||||
useAnalyticsLogDataDirect,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentContainer,
|
||||
getComponentGroupAry,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentContainer,
|
||||
getComponentGroupAry,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentContainer,
|
||||
getComponentGroupAry,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentContainer,
|
||||
getComponentGroupAry,
|
||||
getComponentGroup,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import type {
|
||||
PageDataTemplateComponents,
|
||||
PageDataTemplateComponentSet,
|
||||
@@ -61,7 +66,10 @@ const handleVideoClick = (index: number) => {
|
||||
}
|
||||
|
||||
const stopVideo = () => {
|
||||
playingSlideIndex.value = null
|
||||
// 전환 시간 후 완전히 제거
|
||||
setTimeout(() => {
|
||||
playingSlideIndex.value = null
|
||||
}, 400)
|
||||
}
|
||||
|
||||
const onArrowClick = (direction, targetIndex) => {
|
||||
@@ -74,7 +82,7 @@ onMounted(() => {
|
||||
nextTick(() => {
|
||||
const mainInst = slideThumbnailRef.value?.mainInst
|
||||
if (mainInst) {
|
||||
mainInst.on('moved', stopVideo)
|
||||
mainInst.on('move', stopVideo)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -106,7 +114,9 @@ onMounted(() => {
|
||||
:src="getMediaImgSrcFromItem(item)"
|
||||
alt="main image"
|
||||
class="slide-image"
|
||||
:class="{ 'opacity-0': playingSlideIndex === index }"
|
||||
:class="{
|
||||
'opacity-0': playingSlideIndex === index,
|
||||
}"
|
||||
/>
|
||||
<AtomsButtonPlay
|
||||
v-if="isPassVideo(item, index)"
|
||||
@@ -137,6 +147,9 @@ onMounted(() => {
|
||||
.main-slide {
|
||||
@apply relative aspect-[16/9];
|
||||
}
|
||||
.slide-image {
|
||||
@apply transition-opacity duration-500 ease-in-out;
|
||||
}
|
||||
.btn-play {
|
||||
@apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentGroup,
|
||||
ensureMinimumSlideData,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import { getComponentGroup } from '#layers/utils/dataUtil'
|
||||
import type { Splide as SplideType } from '@splidejs/splide'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
|
||||
@@ -21,7 +18,7 @@ const mainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitle')
|
||||
)
|
||||
const slideData = computed(() => {
|
||||
return ensureMinimumSlideData(props.components)
|
||||
return getComponentContainer(props.components, 'group_sets', { minLength: 4 })
|
||||
})
|
||||
|
||||
const buttonListData = ref(
|
||||
@@ -43,12 +40,7 @@ const slideItemSize = {
|
||||
},
|
||||
}
|
||||
|
||||
const handleChange = (
|
||||
_splide: SplideType,
|
||||
newIndex: number,
|
||||
_oldIndex: number,
|
||||
_destIndex: number
|
||||
) => {
|
||||
const handleChange = (_splide: SplideType, newIndex: number) => {
|
||||
buttonListData.value = getComponentGroupAry(
|
||||
slideData.value[newIndex],
|
||||
'buttonList'
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentGroup,
|
||||
ensureMinimumSlideData,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import { getComponentGroup } from '#layers/utils/dataUtil'
|
||||
import type { Splide as SplideType } from '@splidejs/splide'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
|
||||
@@ -20,9 +17,9 @@ const backgroundData = computed(() =>
|
||||
const mainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitle')
|
||||
)
|
||||
const slideData = computed(() => {
|
||||
return ensureMinimumSlideData(props.components)
|
||||
})
|
||||
const slideData = computed(() =>
|
||||
getComponentContainer(props.components, 'group_sets', { minLength: 4 })
|
||||
)
|
||||
const imgTitleData = ref(getComponentGroup(slideData?.value[0], 'imgTitle'))
|
||||
const descriptionData = ref(
|
||||
getComponentGroup(slideData?.value[0], 'description')
|
||||
|
||||
@@ -44,22 +44,18 @@ const buttonListData = computed(() =>
|
||||
:resources-data="descriptionData"
|
||||
class="w-full max-w-[355px] md:max-w-[944px]"
|
||||
/>
|
||||
<client-only>
|
||||
<WidgetsVideoPlay
|
||||
v-if="videoPlayData"
|
||||
:resources-data="videoPlayData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
/>
|
||||
</client-only>
|
||||
<client-only>
|
||||
<WidgetsButtonList
|
||||
v-if="buttonListData.length > 0"
|
||||
:resources-data="buttonListData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
button-type="market"
|
||||
class="mt-[22px] md:mt-[52px]"
|
||||
/>
|
||||
</client-only>
|
||||
<WidgetsVideoPlay
|
||||
v-if="videoPlayData"
|
||||
:resources-data="videoPlayData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
/>
|
||||
<WidgetsButtonList
|
||||
v-if="buttonListData.length > 0"
|
||||
button-type="market"
|
||||
:resources-data="buttonListData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
class="mt-[22px] md:mt-[52px]"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import {
|
||||
getComponentGroup,
|
||||
getComponentGroupAry,
|
||||
ensureMinimumSlideOperateData,
|
||||
getComponentContainer,
|
||||
} from '#layers/utils/dataUtil'
|
||||
import { formatTimestamp } from '#layers/utils/formatUtil'
|
||||
import { getResolvedHost } from '#layers/utils/styleUtil'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
import type { OperateGroupItem } from '#layers/types/api/resourcesData'
|
||||
|
||||
interface Props {
|
||||
components: PageDataTemplateComponents
|
||||
@@ -16,6 +18,8 @@ const props = defineProps<Props>()
|
||||
|
||||
const pageDataStore = usePageDataStore()
|
||||
const { getResourcesData } = useResourcesData()
|
||||
const { locale } = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const { pageData } = storeToRefs(pageDataStore)
|
||||
|
||||
@@ -31,34 +35,35 @@ const descriptionData = computed(() =>
|
||||
const videoPlayData = computed(() =>
|
||||
getComponentGroup(props.components, 'videoPlay')
|
||||
)
|
||||
const buttonListData = computed(() =>
|
||||
getComponentGroupAry(props.components, 'buttonList')
|
||||
)
|
||||
|
||||
// 비동기 데이터 로딩
|
||||
const { data: resourcesData } = await useLazyAsyncData(
|
||||
'gr-visual-02-resources',
|
||||
const { data: slideData } = await useAsyncData(
|
||||
`gr-visual-02-resources-${pageData.value?.page_seq}-${pageData.value?.page_ver}-${props.pageVerTmplSeq}`,
|
||||
async () => {
|
||||
if (!pageData.value?.page_seq || !pageData.value?.page_ver) {
|
||||
return null
|
||||
return []
|
||||
}
|
||||
|
||||
return await getResourcesData({
|
||||
const operateGroupList = await getResourcesData({
|
||||
pageSeq: pageData.value.page_seq,
|
||||
pageVer: pageData.value.page_ver,
|
||||
pageVerTmplSeq: props.pageVerTmplSeq,
|
||||
langCode: 'ko',
|
||||
})
|
||||
|
||||
const bannerList = getComponentContainer(operateGroupList, 'bannerList', {
|
||||
hasGroup: true,
|
||||
minLength: 4,
|
||||
}) as OperateGroupItem[]
|
||||
|
||||
console.log('bannerList', bannerList)
|
||||
return bannerList
|
||||
},
|
||||
{
|
||||
default: () => [],
|
||||
server: false,
|
||||
}
|
||||
)
|
||||
|
||||
const slideData = computed(() => {
|
||||
if (!resourcesData.value) return []
|
||||
|
||||
const data = getComponentGroupAry(resourcesData.value, 'bannerList')
|
||||
return ensureMinimumSlideOperateData(data)
|
||||
})
|
||||
|
||||
const slideItemSize = {
|
||||
mo: {
|
||||
width: 276,
|
||||
@@ -71,15 +76,12 @@ const slideItemSize = {
|
||||
gap: 32,
|
||||
},
|
||||
}
|
||||
const { locale } = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
const onArrowClick = (direction, targetIndex) => {
|
||||
|
||||
const onArrowClick = direction => {
|
||||
const arrowGroupAry = getComponentGroupAry(props.components, 'arrow')
|
||||
const logTracking = arrowGroupAry?.[direction === 'prev' ? 0 : 1]
|
||||
sendLog(locale.value, useAnalyticsLogDataDirect(logTracking, 1))
|
||||
}
|
||||
|
||||
console.log('resourcesData.value===', resourcesData.value)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -105,17 +107,10 @@ console.log('resourcesData.value===', resourcesData.value)
|
||||
:resources-data="videoPlayData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
/>
|
||||
|
||||
<WidgetsButtonList
|
||||
v-if="buttonListData.length > 0"
|
||||
:resources-data="buttonListData"
|
||||
:page-ver-tmpl-seq="Number(props.pageVerTmplSeq)"
|
||||
class="mt-[48px] md:mt-[72px]"
|
||||
/>
|
||||
<BlocksSlideCenterHighlight
|
||||
v-if="slideData"
|
||||
v-if="slideData && slideData.length > 0"
|
||||
:slide-item-size="slideItemSize"
|
||||
:slide-item-length="slideData?.length"
|
||||
:slide-item-length="slideData.length"
|
||||
:pagination="false"
|
||||
class="mt-[36px] md:mt-[60px]"
|
||||
@arrow-click="onArrowClick"
|
||||
|
||||
@@ -13,10 +13,9 @@ interface Props {
|
||||
pageVerTmplSeq: string
|
||||
}
|
||||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { locale } = useI18n()
|
||||
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
|
||||
|
||||
const slideData = computed(() => {
|
||||
|
||||
@@ -7,13 +7,9 @@ import type {
|
||||
PageDataValue,
|
||||
PageDataResourceContainer,
|
||||
PageDataTemplateComponents,
|
||||
PageDataTemplateComponentSet,
|
||||
PageDataResourceGroupType,
|
||||
} from '#layers/types/api/pageData'
|
||||
import type {
|
||||
OperateComponents,
|
||||
OperateGroupItem,
|
||||
} from '#layers/types/api/resourcesData'
|
||||
import type { OperateComponents } from '#layers/types/api/resourcesData'
|
||||
|
||||
/**
|
||||
* 페이지 데이터를 기반으로 레이아웃 타입을 결정합니다.
|
||||
@@ -64,24 +60,6 @@ export const isTypeButton = (type: PageDataResourceGroupType): boolean => {
|
||||
return type === 'BTN'
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 컨테이너를 반환합니다.
|
||||
* @param components props.components
|
||||
* @param componentName 컴포넌트 이름
|
||||
* @param options 옵션 (maxLength: 최대 길이)
|
||||
* @returns 컴포넌트 컨테이너
|
||||
*/
|
||||
export const getComponentContainer = (
|
||||
components: PageDataTemplateComponents | OperateComponents,
|
||||
componentName: string,
|
||||
{ maxLength }: { maxLength?: number } = {}
|
||||
) => {
|
||||
if (!components) return []
|
||||
|
||||
const container = components[componentName] || []
|
||||
return maxLength ? container.slice(0, maxLength) : container
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 그룹에 데이터가 존재하는지 확인합니다.
|
||||
* @param components props.components 또는 group 객체
|
||||
@@ -98,6 +76,45 @@ export const hasComponentGroup = (
|
||||
return component?.groups && component.groups.length > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 컨테이너를 반환합니다.
|
||||
* @param components props.components
|
||||
* @param componentName 컴포넌트 이름
|
||||
* @param options 옵션
|
||||
* - hasGroup: groups 속성에서 데이터 가져오기 (기본값: false)
|
||||
* - maxLength: 최대 길이 제한
|
||||
* - minLength: 최소 길이 보장 (데이터 반복)
|
||||
* @returns 컴포넌트 컨테이너 배열
|
||||
*/
|
||||
export const getComponentContainer = (
|
||||
components: PageDataTemplateComponents | OperateComponents,
|
||||
componentName: string,
|
||||
options: { hasGroup?: boolean; maxLength?: number; minLength?: number } = {}
|
||||
) => {
|
||||
if (!components) return []
|
||||
|
||||
const { hasGroup = false, maxLength, minLength } = options
|
||||
|
||||
// 1. 초기 컨테이너 가져오기
|
||||
const component = components[componentName]
|
||||
if (!component) return []
|
||||
|
||||
let result = hasGroup && 'groups' in component ? component.groups : component
|
||||
|
||||
// 2. 최소 길이 보장 (데이터 복제)
|
||||
if (minLength && result.length > 1 && result.length < minLength) {
|
||||
const repeatTimes = Math.ceil(minLength / result.length)
|
||||
result = Array(repeatTimes).fill(result).flat()
|
||||
}
|
||||
|
||||
// 3. 최대 길이 제한
|
||||
if (maxLength && result.length > maxLength) {
|
||||
return result.slice(0, maxLength)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 그룹의 첫 번째 데이터를 반환합니다.
|
||||
* @param components props.components 또는 group 객체
|
||||
@@ -128,52 +145,6 @@ export const getComponentGroupAry = (
|
||||
return components[componentName]?.groups || []
|
||||
}
|
||||
|
||||
/**
|
||||
* 슬라이드 데이터를 최소 개수로 보장합니다. (페이지 데이터용)
|
||||
* @param components 원본 데이터 배열 또는 객체
|
||||
* @param minCount 최소 보장할 개수 (기본값: 3)
|
||||
* @returns 최소 개수가 보장된 데이터 배열
|
||||
*/
|
||||
export const ensureMinimumSlideData = (
|
||||
components: PageDataTemplateComponents,
|
||||
minCount: number = 4
|
||||
): PageDataTemplateComponentSet[] => {
|
||||
if (!components) return []
|
||||
|
||||
const arrayData = Array.isArray(components.group_sets)
|
||||
? components.group_sets
|
||||
: []
|
||||
|
||||
// 빈 배열이거나 이미 최소 개수를 만족하면 그대로 반환
|
||||
if (arrayData.length <= 1 || arrayData.length >= minCount) {
|
||||
return arrayData
|
||||
}
|
||||
|
||||
// 최소 개수를 보장하기 위해 데이터 반복
|
||||
const repeatTimes = Math.ceil(minCount / arrayData.length)
|
||||
return Array(repeatTimes).fill(arrayData).flat()
|
||||
}
|
||||
|
||||
/**
|
||||
* 슬라이드 데이터를 최소 개수로 보장합니다. (운영 그룹용)
|
||||
* @param data 원본 데이터 배열
|
||||
* @param minCount 최소 보장할 개수 (기본값: 3)
|
||||
* @returns 최소 개수가 보장된 데이터 배열
|
||||
*/
|
||||
export const ensureMinimumSlideOperateData = (
|
||||
data: OperateGroupItem[],
|
||||
minCount: number = 4
|
||||
): OperateGroupItem[] => {
|
||||
// 빈 배열이거나 이미 최소 개수를 만족하면 그대로 반환
|
||||
if (data.length <= 1 || data.length >= minCount) {
|
||||
return data
|
||||
}
|
||||
|
||||
// 최소 개수를 보장하기 위해 데이터 반복
|
||||
const repeatTimes = Math.ceil(minCount / data.length)
|
||||
return Array(repeatTimes).fill(data).flat()
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 시간의 타임스탬프를 반환합니다.
|
||||
* @param unit 단위 ('ms' | 's') - 밀리초 또는 초
|
||||
|
||||
Reference in New Issue
Block a user