Files
web-temp/layers/components/widgets/ButtonList.vue
2026-01-22 14:22:38 +09:00

158 lines
4.2 KiB
Vue

<script setup lang="ts">
import type {
PageDataResourceGroup,
PageDataResourceGroupBtnInfo,
} from '#layers/types/api/pageData'
import type { ButtonType } from '#layers/types/components/button'
interface Props {
resourcesData: PageDataResourceGroup[]
buttonSize?: string
}
const props = withDefaults(defineProps<Props>(), {
buttonSize: 'size-extra-small md:size-medium',
})
const { locale, tm } = useI18n()
const device = useDevice()
const modalStore = useModalStore()
const scrollStore = useScrollStore()
const breakpoints = useResponsiveBreakpoints()
const { sendLog } = useAnalytics()
const buttonList = computed<PageDataResourceGroup[]>(
() => props.resourcesData ?? []
)
const getButtonType = (btnInfo?: PageDataResourceGroupBtnInfo): ButtonType => {
const btnType = btnInfo?.detail?.btn_type
const target = btnInfo?.detail?.action?.link_target
if (btnType === 'URL' && target) {
return target === '_blank' ? 'external' : 'internal'
}
if (btnType === 'DOWNLOAD') return 'download'
return 'action'
}
const isRunButtonVisible = (btnInfo: PageDataResourceGroupBtnInfo): boolean => {
if (breakpoints.value?.isDesktop) return true
const marketType = btnInfo?.detail?.market_type
switch (marketType) {
case 'pc':
return false
case 'google_play':
return device.isAndroid
case 'app_store':
return device.isApple
default:
return true
}
}
const downloadFile = async (url: string = '', osType: number = 0) => {
if (osType === 1 && breakpoints.value?.isMobile) {
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_PC') })
return
}
const fileUrl = formatPathHost(url)
try {
const res = await $fetch<Blob>(fileUrl, {
method: 'GET',
responseType: 'blob',
timeout: 10000,
})
const blob = res
const blobUrl = URL.createObjectURL(blob)
const pathPart = fileUrl.split('/').pop() ?? 'download'
const a = document.createElement('a')
a.href = blobUrl
a.download = pathPart
document.body.appendChild(a)
a.click()
a.remove()
// 메모리 정리
URL.revokeObjectURL(blobUrl)
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_Success') })
} catch (err) {
console.error(err)
modalStore.handleOpenAlert({ contentText: tm('Alert_Download_Error') })
}
}
const handleButtonClick = (button: PageDataResourceGroup) => {
sendLog(locale.value, button.tracking)
const btnDetail = button.btn_info?.detail
switch (btnDetail?.btn_type) {
case 'POP':
modalStore.handleOpenContent({
contentTitle: btnDetail?.title,
tabInfo: btnDetail?.tab_info,
})
return
case 'ANCHOR':
scrollStore.scrollToAnchor(btnDetail?.page_ver_tmpl_name_en ?? '')
return
case 'MOV':
modalStore.handleOpenYoutube({ youtubeUrl: btnDetail.url ?? '' })
return
case 'DOWNLOAD':
downloadFile(btnDetail?.file_path, btnDetail?.os_type)
return
default:
return
}
}
</script>
<template>
<div
v-if="buttonList.length"
v-motion-stagger
class="flex flex-wrap justify-center gap-3 md:gap-4"
>
<template v-for="(button, index) in buttonList" :key="index">
<template v-if="button.btn_info?.detail?.btn_type === 'RUN'">
<BlocksButtonLauncher
v-if="isRunButtonVisible(button.btn_info)"
type="duplication"
:platform="button.btn_info?.detail?.market_type"
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
@click="handleButtonClick(button)"
>
{{ button.btn_info?.txt_btn_name }}
</BlocksButtonLauncher>
</template>
<AtomsButton
v-else
:type="getButtonType(button.btn_info)"
:size="buttonSize"
:href="button.btn_info?.detail?.action?.url"
:target="button.btn_info?.detail?.action?.link_target"
:background-color="getColorCodeFromData(button.btn_info, 'btn')"
:text-color="getColorCodeFromData(button.btn_info, 'txt')"
:disabled="button.btn_info?.detail?.btn_type === 'DEACTIVE'"
@click="handleButtonClick(button)"
>
{{ button.btn_info?.txt_btn_name }}
</AtomsButton>
</template>
</div>
</template>