feat. home 버튼 컴포넌트 추가

This commit is contained in:
clkim
2025-11-11 18:50:14 +09:00
parent 25ea7925ea
commit 4ca00e4028
20 changed files with 216 additions and 317 deletions

View File

@@ -41,9 +41,18 @@
<div class="inspection-bottom-cards">
<!-- 온스토브 카드 -->
<div class="inspection-card inspection-stove-card">
<h3 :class="{ 'text-center': !launchingStatus }" class="card-title text-base md:text-lg">
<span v-if="!launchingStatus" v-dompurify-html="tm('Inspection_Game_During_Maintenance')"></span>
<span v-else v-dompurify-html="tm('org_Inspection_During_Maintenance')"></span>
<h3
:class="{ 'text-center': !launchingStatus }"
class="card-title text-base md:text-lg"
>
<span
v-if="!launchingStatus"
v-dompurify-html="tm('Inspection_Game_During_Maintenance')"
></span>
<span
v-else
v-dompurify-html="tm('org_Inspection_During_Maintenance')"
></span>
</h3>
<div class="button-group justify-center">
<!-- <a
@@ -103,7 +112,7 @@
{{ tm('Inspection_Txt_Download') || '게임 다운로드' }}
</h3>
<div class="flex flex-row gap-3">
<AtomsButtonLauncher
<BlocksButtonLauncher
v-for="(btn, index) in enabledMarkets"
:key="index"
:class="getButtonClass(btn.platform)"
@@ -114,7 +123,7 @@
variant="outlined"
>
{{ getButtonText(btn.platform) }}
</AtomsButtonLauncher>
</BlocksButtonLauncher>
</div>
</div>
</div>
@@ -131,7 +140,7 @@ import { useCheckGameStart } from '#layers/composables/useGameStart'
const config = useRuntimeConfig()
const dataResourcesUrl = config.public.dataResourcesUrl as string
const multilingualFileName = 'STOVE_PUBTEMPLATE_homepage_brand_inspection.json'
// const isClient = import.meta.client
const inspectionStore = useInspectionStore()
@@ -160,21 +169,21 @@ const getLocaleTimezone = (localeType: string, region) => {
const tsStartDate = webInspectionData.value?.ts_start_date || 0
const tsEndDate = webInspectionData.value?.ts_end_date || 0
const currentLocale = localeType || locale.value
const timezoneMap: Record<string, string> = {
'ko': 'KST',
ko: 'KST',
'zh-tw': '台灣時間',
'ja': 'JST',
ja: 'JST',
}
const timezone = timezoneMap[currentLocale] || 'KST'
const defaultRegion = currentLocale === 'ko' ? 'KR' : ''
const formatDate = (date: Date, loc: string, reg: string) =>
`${globalDateFormat(date, loc, reg || defaultRegion, {useFullDate: true})}`
const formatDate = (date: Date, loc: string, reg: string) =>
`${globalDateFormat(date, loc, reg || defaultRegion, { useFullDate: true })}`
const localTime = `${formatDate(new Date(tsStartDate), currentLocale, region || '')} <br class="md:hidden">~ ${formatDate(new Date(tsEndDate), currentLocale, region || '')} (${timezone})`
const utcTime = `${formatDate(new Date(tsStartDate), 'en', region || '')} <br class="md:hidden">~ ${formatDate(new Date(tsEndDate), 'en', region || '')} (UTC)`
return currentLocale === 'en' ? utcTime : `${localTime}<br>${utcTime}`
}
@@ -252,7 +261,6 @@ const handleGameStart = () => {
validateLauncher()
}
definePageMeta({
middleware: ['inspection'],
layout: 'only-stove',

View File

@@ -0,0 +1,50 @@
<script setup lang="ts">
interface props {
type?: 'button' | 'link'
to?: string
target?: '_self' | '_blank'
srOnly?: string
}
const props = withDefaults(defineProps<props>(), {
type: 'button',
to: '',
target: '_self',
srOnly: '',
})
const componentTag = computed((): string => {
switch (props.type) {
case 'link':
return 'AtomsLocaleLink'
default:
return 'button'
}
})
const componentProps = computed(() => {
switch (props.type) {
case 'link':
return { to: props.to, target: props.target }
default:
return {}
}
})
</script>
<template>
<component :is="componentTag" v-bind="componentProps" class="btn-circle">
<slot />
<span class="sr-only">{{ props.srOnly }}</span>
</component>
</template>
<style scoped>
.btn-circle {
@apply relative flex items-center justify-center rounded-full
w-[40px] h-[40px] md:w-[48px] md:h-[48px]
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-[rgba(255,255,255,0.06)] before:rounded-full
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-full after:opacity-0 after:transition-all after:duration-300 after:ease-in-out
hover:after:opacity-10;
}
</style>

View File

@@ -1,28 +0,0 @@
<script setup lang="ts">
const { y: windowY } = useWindowScroll({ behavior: 'smooth' })
const showBtn = computed(() => windowY.value > 0)
const handleScrollToTop = () => {
windowY.value = 0
}
</script>
<template>
<Transition name="fade">
<button v-show="showBtn" class="btn-top" @click="handleScrollToTop">
<span class="sr-only">top</span>
</button>
</Transition>
</template>
<style scoped>
.btn-top {
@apply relative rounded-full bg-[image:var(--button-top)] bg-center bg-cover bg-no-repeat
w-[40px] h-[40px] md:w-[48px] md:h-[48px]
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-full after:opacity-0 after:transition-all after:duration-300 after:ease-in-out;
}
.btn-top:hover {
@apply after:opacity-10;
}
</style>

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
interface Props {
size?: number | string
color?: string
}
withDefaults(defineProps<Props>(), {
size: 24,
color: 'white',
})
</script>
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
:width="size"
:height="size"
viewBox="0 0 24 24"
:fill="color"
>
<path
d="M10.7388 3.23622C11.4736 2.63919 12.5264 2.63919 13.2612 3.23622L20.6306 9.22387C20.8643 9.41376 21 9.69885 21 9.99998L21 19C21 20.1045 20.1046 21 19 21L14 21C13.4477 21 13 20.5523 13 20V14.125C13 13.5037 12.5523 13 12 13C11.4477 13 11 13.5037 11 14.125L11 20C11 20.5523 10.5523 21 10 21H5C3.89543 21 3 20.1045 3 19L3 9.99998C3 9.69885 3.1357 9.41376 3.36941 9.22387L10.7388 3.23622Z"
/>
</svg>
</template>

View File

@@ -0,0 +1,26 @@
<script setup lang="ts">
const scrollStore = useScrollStore()
const { isPassedStoveGnb } = storeToRefs(scrollStore)
</script>
<template>
<AtomsButtonCircle
sr-only="home"
type="link"
to="/"
:class="['btn-home', { 'is-fixed': isPassedStoveGnb }]"
>
<AtomsIconsHomeFill />
</AtomsButtonCircle>
</template>
<style scoped>
.btn-home {
@apply absolute top-3 right-3 mt-[48px] bg-black/20 shadow-[0_1.667px_3.333px_0_rgba(0,0,0,0.06)] backdrop-blur-[12.5px] z-[100]
sm:top-5 md:top-6 md:right-8 md:mt-[64px];
}
.btn-home.is-fixed {
@apply fixed;
}
</style>

View File

@@ -0,0 +1,26 @@
<script setup lang="ts">
const { y: windowY } = useWindowScroll({ behavior: 'smooth' })
const showBtn = computed(() => windowY.value > 0)
const handleScrollToTop = () => {
windowY.value = 0
}
</script>
<template>
<Transition name="fade">
<AtomsButtonCircle
v-show="showBtn"
class="btn-top"
sr-only="top"
@click="handleScrollToTop"
/>
</Transition>
</template>
<style scoped>
.btn-top {
@apply bg-[image:var(--button-top)] bg-center bg-cover bg-no-repeat;
}
</style>

View File

@@ -42,14 +42,14 @@ const handleCopy = async () => {
<template>
<div v-if="Object.keys(snsList).length > 0" class="sns-container">
<button
<AtomsButtonCircle
class="btn-sns"
sr-only="sns"
:style="{ backgroundColor: snsBackgroundColor }"
@click="handleMouseEnter"
>
<AtomsIconsShareLine class="icon-share" />
<span class="sr-only">sns</span>
</button>
</AtomsButtonCircle>
<transition name="fade">
<div
v-if="showSnsList"
@@ -95,15 +95,6 @@ const handleCopy = async () => {
</template>
<style scoped>
.btn-sns {
@apply relative rounded-full flex items-center justify-center
w-[40px] h-[40px] md:w-[48px] md:h-[48px]
before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-full before:border before:border-[rgba(255,255,255,0.06)] before:rounded-full
after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-white after:rounded-full after:opacity-0 after:transition-all after:duration-300 after:ease-in-out;
}
.btn-sns:hover {
@apply after:opacity-10;
}
.btn-sns:hover .icon-share {
@apply fill-white;
}

View File

@@ -147,7 +147,7 @@ onUnmounted(() => {
<style scoped>
.lnb-wrap {
@apply fixed top-1/2 right-0 py-12 pr-4 text-right -translate-y-1/2 bg-[radial-gradient(100%_50%_at_100%_50%,rgba(0,0,0,0.5)_25%,rgba(0,0,0,0)_100%)] z-50;
@apply fixed top-1/2 right-0 py-12 pr-[42px] text-right -translate-y-1/2 bg-[radial-gradient(100%_50%_at_100%_50%,rgba(0,0,0,0.5)_25%,rgba(0,0,0,0)_100%)] z-50;
}
.main-list {
@apply flex flex-col gap-4 items-end;
@@ -163,10 +163,22 @@ onUnmounted(() => {
}
button {
@apply font-[500] text-[var(--lnb-disable-color)] transition-all duration-300 ease-in-out;
@apply relative font-[500] text-[var(--lnb-disable-color)] transition-all duration-300 ease-in-out;
}
button:hover,
button.is-active {
@apply text-[var(--lnb-active-color)];
}
button::before {
@apply content-[''] absolute top-1/2 rounded-full -translate-y-1/2 bg-transparent transition-all duration-300 ease-in-out;
}
button.is-active::before {
@apply bg-[var(--lnb-active-color)];
}
.btn-1depth::before {
@apply -right-4 w-1.5 h-1.5;
}
.btn-2depth::before {
@apply -right-3.5 w-1 h-1;
}
</style>

View File

@@ -1,211 +0,0 @@
<script setup lang="ts">
import type { PageDataLnbMenu } from '#layers/types/api/pageData'
const HEADER_HEIGHT = 64
const { y: windowY } = useWindowScroll({ behavior: 'smooth' })
const pageDataStore = usePageDataStore()
const breakpoints = useResponsiveBreakpoints()
const { pageData } = storeToRefs(pageDataStore)
const activeSection = ref<string>('')
const observerRef = shallowRef<IntersectionObserver | null>(null)
/** 1뎁스 LNB 배열로 정규화 */
const lnbRoot = computed<PageDataLnbMenu[]>(() =>
Object.values(pageData.value?.lnb_menus || {}).filter(Boolean)
)
const isShowLnb = computed(() => {
const pageDataUseLnb = pageData.value?.use_lnb ?? false
const isDesktop = breakpoints.value.isDesktop
const lnbRootLength = lnbRoot.value.length
return Boolean(pageDataUseLnb && isDesktop && lnbRootLength)
})
const activeColor = computed(
() => pageData.value?.lnb_text_color_code_active || 'var(--text-primary)'
)
const disableColor = computed(
() => pageData.value?.lnb_text_color_code_deactive || 'var(--text-secondary)'
)
const getChildren = (item?: PageDataLnbMenu) =>
item?.children ? Object.values(item.children) : []
/** 1뎁스 활성 판정(자신 또는 자식) */
const is1DepthActive = (lnbItem: PageDataLnbMenu): boolean => {
if (!lnbItem) return false
if (activeSection.value === lnbItem.page_ver_tmpl_name_en) return true
return getChildren(lnbItem).some(
c => activeSection.value === c.page_ver_tmpl_name_en
)
}
/** 스크롤 이동 */
const scrollToLnb = async (id: string) => {
if (import.meta.server) return
await nextTick()
const el = document.getElementById(id)
if (!el) return
const rect = el.getBoundingClientRect()
const targetY = window.scrollY + rect.top - HEADER_HEIGHT
windowY.value = targetY
}
/** 관찰 대상 id 리스트(1뎁스 + 2뎁스) */
const sectionIds = computed<string[]>(() => {
const ids: string[] = []
for (const item of lnbRoot.value) {
if (item?.page_ver_tmpl_name_en) ids.push(item.page_ver_tmpl_name_en)
for (const c of getChildren(item)) {
if (c?.page_ver_tmpl_name_en) ids.push(c.page_ver_tmpl_name_en)
}
}
// 중복 제거
return Array.from(new Set(ids))
})
const createObserver = () => {
if (observerRef.value) observerRef.value.disconnect()
observerRef.value = new IntersectionObserver(
entries => {
// 보이는 섹션 중 화면 상단에 가장 가까운 요소를 활성화
const visibles = entries
.filter(e => e.isIntersecting)
.sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)
if (visibles.length > 0) {
activeSection.value = (visibles[0].target as HTMLElement).id
return
}
// 가끔 빠르게 스크롤 시 entries가 비어있을 수 있으므로
// 현재 모든 섹션 중에서 '상단 기준으로 가장 가까운' 것을 폴백 계산
const candidates: Array<{ id: string; top: number }> = []
for (const id of sectionIds.value) {
const el = document.getElementById(id)
if (!el) continue
const top = el.getBoundingClientRect().top - HEADER_HEIGHT
candidates.push({ id, top })
}
// 0에 가장 가까운 양수/음수 모두 고려(위/아래 가장 가까운)
candidates.sort((a, b) => Math.abs(a.top) - Math.abs(b.top))
if (candidates.length) activeSection.value = candidates[0].id
},
{
root: null,
// 상단 20%, 하단 60% 마진은 유지하되 헤더 보정치 반영
rootMargin: `-${Math.max(HEADER_HEIGHT, 20)}px 0px -60% 0px`,
threshold: 0,
}
)
}
const handleLnbClick = (lnbItem: PageDataLnbMenu) => {
if (!lnbItem?.page_ver_tmpl_name_en) return
scrollToLnb(lnbItem.page_ver_tmpl_name_en)
}
const observeSections = () => {
if (import.meta.server) return
if (!observerRef.value) createObserver()
const obs = observerRef.value!
obs.disconnect() // 기존 관찰 해제
// DOM 렌더 후 관찰 등록
requestAnimationFrame(() => {
for (const id of sectionIds.value) {
const el = document.getElementById(id)
if (el) obs.observe(el)
}
})
}
onMounted(() => {
if (import.meta.server) return
createObserver()
observeSections()
})
// lnb 데이터/DOM이 바뀌면 재관찰
watchEffect(async () => {
if (!import.meta.client) return
if (isShowLnb.value && sectionIds.value.length) {
await nextTick()
observeSections()
}
})
onUnmounted(() => {
observerRef.value?.disconnect()
observerRef.value = null
})
</script>
<template>
<div
v-if="isShowLnb"
class="lnb-wrap"
:style="{
'--lnb-active-color': activeColor,
'--lnb-disable-color': disableColor,
}"
>
<ul class="main-list">
<li v-for="lnbItem in lnbRoot" :key="lnbItem.path_code">
<button
v-dompurify-html="lnbItem.menu_name"
type="button"
:class="['btn-1depth', { 'is-active': is1DepthActive(lnbItem) }]"
@click="handleLnbClick(lnbItem)"
></button>
<ul v-if="getChildren(lnbItem).length > 0" class="sub-list">
<li v-for="subItem in getChildren(lnbItem)" :key="subItem.path_code">
<button
v-dompurify-html="subItem.menu_name"
type="button"
:class="[
'btn-2depth',
{
'is-active': activeSection === subItem.page_ver_tmpl_name_en,
},
]"
@click="handleLnbClick(subItem)"
></button>
</li>
</ul>
</li>
</ul>
</div>
</template>
<style scoped>
.lnb-wrap {
@apply fixed top-1/2 right-0 py-12 pr-4 text-right -translate-y-1/2 bg-[radial-gradient(100%_50%_at_100%_50%,rgba(0,0,0,0.5)_25%,rgba(0,0,0,0)_100%)] z-50;
}
.main-list {
@apply flex flex-col gap-4 items-end;
}
.btn-1depth {
@apply text-[15px] leading-[26px] tracking-[-0.54px];
}
.sub-list {
@apply flex flex-col gap-2 items-end mt-4 mb-1 pr-[46px];
}
.btn-2depth {
@apply text-[14px] leading-[20px] tracking-[-0.42px];
}
button {
@apply font-[500] text-[var(--lnb-disable-color)] transition-all duration-300 ease-in-out;
}
button:hover,
button.is-active {
@apply text-[var(--lnb-active-color)];
}
</style>

View File

@@ -58,16 +58,13 @@ onMounted(async () => {
}"
>
<div class="navigation-wrapper">
<button class="btn-control" @click="toggleEventNavigation">
<AtomsButtonCircle
sr-only="event navigation control"
class="btn-control"
@click="toggleEventNavigation"
>
<AtomsIconsArrowRightLine size="24" color="#ffffff" />
<span class="sr-only">
{{
isEventNavigationOpen
? 'event navigation close'
: 'event navigation open'
}}
</span>
</button>
</AtomsButtonCircle>
<ul class="navigation-list">
<li v-for="item in eventNavigationList" :key="item.banner_seq">
<AtomsLocaleLink
@@ -95,7 +92,7 @@ onMounted(async () => {
<style scoped>
.event-navigation {
@apply absolute top-0 left-0 bottom-0 pt-[48px] md:pt-[64px] z-[100] transition-transform duration-300 ease-in-out;
@apply absolute top-0 left-0 bottom-0 mt-[48px] md:mt-[64px] z-[100] transition-transform duration-300 ease-in-out;
}
.event-navigation.is-fixed {
@apply fixed;
@@ -116,9 +113,9 @@ onMounted(async () => {
@apply block mt-2 text-center line-clamp-2 text-[#ebebeb] text-[14px] font-normal leading-[20px] tracking-[-0.42px] opacity-50;
}
.btn-control {
@apply absolute top-3 right-[-40px] flex items-center justify-center w-[40px] h-[40px] transition-transform duration-300 ease-in-out
bg-black/20 shadow-[0_1.667px_3.333px_0_rgba(0,0,0,0.06)] backdrop-blur-[12.5px] rounded-full
sm:top-5 md:top-6 md:right-[-48px] md:w-[48px] md:h-[48px];
@apply absolute top-3 right-[-40px]
bg-black/20 shadow-[0_1.667px_3.333px_0_rgba(0,0,0,0.06)] backdrop-blur-[12.5px]
sm:top-5 md:top-6 md:right-[-48px];
}
.event-navigation.is-closed {

View File

@@ -317,7 +317,7 @@ onBeforeUnmount(() => {
</div>
</nav>
<div ref="startRef" class="btn-start">
<AtomsButtonLauncher
<BlocksButtonLauncher
type="custom"
platform="pc"
:background-color="
@@ -334,13 +334,13 @@ onBeforeUnmount(() => {
"
>
{{ gnb1depthButtonData?.btn_info?.txt_btn_name }}
</AtomsButtonLauncher>
</BlocksButtonLauncher>
<div v-if="gnb2depthButtonData" class="nav-2depth hidden md:block">
<ul>
<li v-for="(item, key) in gnb2depthButtonData" :key="key">
<AtomsButtonLauncher type="custom" :platform="key">
<BlocksButtonLauncher type="custom" :platform="key">
{{ item.btn_info?.txt_btn_name }}
</AtomsButtonLauncher>
</BlocksButtonLauncher>
</li>
</ul>
</div>
@@ -361,7 +361,7 @@ onBeforeUnmount(() => {
<style scoped>
.header {
@apply bg-theme-foreground text-theme-foreground-reversal relative z-[110];
@apply bg-theme-foreground text-theme-foreground-reversal relative z-[100];
}
.game-wrap {
@apply absolute flex w-full h-[48px] items-center whitespace-nowrap px-[52px] bg-theme-foreground sm:px-[72px] md:h-16 md:pl-0 md:pr-[40px]

View File

@@ -52,7 +52,7 @@ const setupSeoMeta = (metaTag: PageDataMetaTag) => {
onMounted(() => {
const { sendLog } = useAnalytics()
sendLog(locale.value, useAnalyticsLogDataDirect('view', 1))
// sendLog(locale.value, useAnalyticsLogDataDirect('view', 1))
})
// 메타 태그 설정 감시
@@ -82,8 +82,8 @@ watchEffect(() => {
v-if="isShowTopBtn || isShowSnsBtn"
:class="['utile-wrap', { 'is-stop': pinToMain }]"
>
<AtomsButtonScrollTop v-if="isShowTopBtn" />
<AtomsButtonSns v-if="isShowSnsBtn" />
<BlocksButtonScrollTop v-if="isShowTopBtn" />
<BlocksButtonSns v-if="isShowSnsBtn" />
</div>
</ClientOnly>
</div>

View File

@@ -12,6 +12,7 @@ interface Props {
const props = defineProps<Props>()
const { locale } = useI18n()
const modalStore = useModalStore()
const { sendLog, useAnalyticsLogDataDirect } = useAnalytics()
const getBtnType = (item?: PageDataResourceGroupBtnInfo): ButtonType => {
@@ -35,11 +36,16 @@ const getTextColor = (item?: PageDataResourceGroupBtnInfo): string =>
colorCode: item?.color_code_txt,
})
const handleLogClick = (index: number) => {
sendLog(
locale.value,
useAnalyticsLogDataDirect(props.resourcesData[index], props.pageVerTmplSeq)
)
const handleLogClick = (button: PageDataResourceGroup) => {
sendLog(locale.value, useAnalyticsLogDataDirect(button, props.pageVerTmplSeq))
if (button.btn_info?.detail?.btn_type === 'POP') {
const popupSize = button.btn_info?.detail?.size_info
const popupTitle = button.btn_info?.detail?.title
const popupContent = button.btn_info?.detail?.tab_info[0].title
modalStore.handleOpenAlert({
contentText: popupContent,
})
}
}
// 편의상
@@ -52,17 +58,17 @@ const buttonList = computed(() => props.resourcesData || [])
class="flex flex-wrap justify-center gap-3 md:gap-4"
>
<template v-for="(button, index) in buttonList" :key="index">
<AtomsButtonLauncher
<BlocksButtonLauncher
v-if="button.btn_info?.detail?.btn_type === 'RUN'"
type="duplication"
:platform="button.btn_info?.detail?.market_type"
:background-color="getBgColor(button.btn_info)"
:text-color="getTextColor(button.btn_info)"
:disabled="button?.btn_info?.disabled"
@click="handleLogClick(index)"
@click="handleLogClick(button)"
>
{{ button.btn_info?.txt_btn_name }}
</AtomsButtonLauncher>
</BlocksButtonLauncher>
<AtomsButton
v-else
:type="getBtnType(button.btn_info)"
@@ -72,7 +78,7 @@ const buttonList = computed(() => props.resourcesData || [])
:background-color="getBgColor(button.btn_info)"
:text-color="getTextColor(button.btn_info)"
:disabled="button?.btn_info?.disabled"
@click="handleLogClick(index)"
@click="handleLogClick(button)"
>
{{ button.btn_info?.txt_btn_name }}
</AtomsButton>

View File

@@ -40,7 +40,7 @@ export const useAnalyticsLogDataDirect = (
logData.viewArea = pageData.page_name_en
logData.viewType = 'pageView'
}
return logData
}
@@ -53,15 +53,15 @@ export const useAnalyticsLogDataDirect = (
eventCategory: `${pageData.page_name}_${pageDataTrack?.click_sarea}_${pageDataTrack?.click_item}`,
} as unknown as AnalyticsDetailType
if(pageDataTrack.action_type === 'click') {
if (pageDataTrack.action_type === 'click') {
logData.clickArea = pageData.page_name_en
logData.clickSarea = pageDataTrack.click_sarea
logData.clickItem = pageDataTrack.click_item
} else if(pageDataTrack.action_type === 'view') {
} else if (pageDataTrack.action_type === 'view') {
logData.viewArea = pageData.page_name_en
logData.viewType = 'view_frame'
}
return logData
}
@@ -225,8 +225,6 @@ const sendSA = (
* @param {AnalyticsDetailType} analytics
*/
const sendLog = (locale: string, analytics: AnalyticsDetailType) => {
console.log('🚀 ~ sendLog ~ analytics:', analytics)
// 언어 코드 대문자 변환
analytics.eventLocale = locale.toUpperCase()

View File

@@ -12,14 +12,13 @@ export const useGetGameDataExternal = () => {
const webGameData = ref<GameDataResponse | null>(null)
const getGameDataExternal = async (req: GameDataRequest) => {
console.log('🚀 ~ getGameDataExternal ~ req:', req)
const runtimeConfig = useRuntimeConfig()
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
const apiUrl = `${stoveApiBaseUrl}/pub-comm/v1.0/template/game?game_domain=${req.gameDomain}&lang_code=${req.langCode}`
try {
const response = (await commonFetch('GET', apiUrl)) as GameDataResponse
console.log('🚀 ~ getGameDataExternal ~ response:', response)
console.log('🚀 ~ getGameDataExternal:', response.value)
// FIXME: 테스트용 데이터 ---------------------------------------------------
/* if (['local', 'local-gate8', 'dev'].includes(`${runtimeConfig.public.runType}`)) {

View File

@@ -15,6 +15,7 @@ provide('pinToMain', pinToMain)
<template>
<LayoutsHeader />
<main id="LayoutsMain" ref="mainRef" class="relative">
<BlocksButtonHome />
<LayoutsEventNavigation />
<slot />
</main>

View File

@@ -2,10 +2,9 @@ export default defineNuxtRouteMiddleware(async to => {
try {
if (import.meta.client) {
const gameDataStore = useGameDataStore()
const { gameData } = storeToRefs(gameDataStore)
console.log('🚀 ~ 00000 gameData:', gameData.value)
const runtimeConfig = useRuntimeConfig()
const { gameData } = storeToRefs(gameDataStore)
// const baseDomain = `${runtimeConfig.public.baseDomain}`
const stoveApiBaseUrl = runtimeConfig.public.stoveApiUrl
const stoveGameId = gameData.value.game_id

View File

@@ -217,13 +217,13 @@ const handleMoveFocus = (target: 'pc' | 'mobile') => {
>
<template v-if="platform === 'MOBILE'">
<template v-for="os in mobileOSList" :key="os.id">
<AtomsButtonLauncher
<BlocksButtonLauncher
v-if="device.isMobile ? os.isValue : true"
:platform="`${os.platformCode as Platform}`"
class="!w-full"
>
<span>{{ os.platformText }}</span>
</AtomsButtonLauncher>
</BlocksButtonLauncher>
</template>
</template>
<template v-else>
@@ -238,13 +238,13 @@ const handleMoveFocus = (target: 'pc' | 'mobile') => {
>
<span>{{ tm(`Download_Button_${platform}_Mobile`) }}</span>
</AtomsButton>
<AtomsButtonLauncher
<BlocksButtonLauncher
v-else-if="breakpoints.isMd || breakpoints.isDesktop"
:platform="`${platform.toLowerCase() as Platform}`"
class="!w-full"
>
<span>{{ tm(`Download_Button_${platform}`) }}</span>
</AtomsButtonLauncher>
</BlocksButtonLauncher>
</template>
</div>
</SplideSlide>

View File

@@ -270,7 +270,7 @@ const handlePreregistClick = () => {
</div>
</div>
<div class="flex gap-3 justify-center flex-wrap mt-8 md:gap-2.5">
<AtomsButtonLauncher
<BlocksButtonLauncher
type="duplication"
platform="stove"
:background-color="buttonColors.backgroundColor"
@@ -278,8 +278,8 @@ const handlePreregistClick = () => {
@click="handlePreregistClick"
>
{{ tm('Preregist_Btn_Preegist') }}
</AtomsButtonLauncher>
<AtomsButtonLauncher
</BlocksButtonLauncher>
<BlocksButtonLauncher
v-for="platform in platformButtons"
:key="`preregist-${platform}`"
type="duplication"
@@ -288,7 +288,7 @@ const handlePreregistClick = () => {
:text-color="buttonColors.textColor"
>
{{ tm('Preregist_Btn_Preegist') }}
</AtomsButtonLauncher>
</BlocksButtonLauncher>
</div>
<WidgetsDescription
v-if="preDescriptionData"