feat. FX_PREREGIST_01 템플릿 제작
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
import { SplideSlide } from '@splidejs/vue-splide'
|
||||
import { getComponentGroup, getComponentGroupAry } from '#layers/utils/dataUtil'
|
||||
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
|
||||
import type { OperateGroupItem } from '#layers/types/api/resourcesData'
|
||||
import type { Platform } from '#layers/types/components/button'
|
||||
|
||||
interface Props {
|
||||
components: PageDataTemplateComponents
|
||||
@@ -10,598 +12,357 @@ interface Props {
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const { tm } = useI18n()
|
||||
|
||||
const test = {
|
||||
subTitle: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '사전 등록 기간 + 2024.06.04 ~ 정식 오픈 전까지',
|
||||
color_code: '',
|
||||
color_name: 'primary',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
mainTitle: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '로드나인 사전 등록',
|
||||
color_code: '',
|
||||
color_name: 'primary',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
background: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo: '/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg_m.jpg',
|
||||
path_pc: '/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg.jpg',
|
||||
},
|
||||
resource_type: 'IMG_COMM',
|
||||
},
|
||||
],
|
||||
},
|
||||
txtSnsLink: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: 'https://pf.kakao.com/_xmyxjpG',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: 'https://www.youtube.com/@LORDNINE_KR',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
description: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '로드나인은 PC, GooglePlay, AppStore에서 즐기실 수 있습니다',
|
||||
color_code: '',
|
||||
color_name: 'text-primary',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
imgAccReward: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '골드 100,000',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward01_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward01.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '중급 물약 x100',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward02_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward02.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '방어구 강화석 x3',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward03_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward03.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '무기 강화석 x3',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward04_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward04.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
// {
|
||||
// display: {
|
||||
// text: '순수한 무기 강화석 x1',
|
||||
// },
|
||||
// res_path: {
|
||||
// path_mo:
|
||||
// '/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward05_m.png',
|
||||
// path_pc:
|
||||
// '/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward05.png',
|
||||
// },
|
||||
// resource_type: 'IMG_LANG',
|
||||
// },
|
||||
],
|
||||
},
|
||||
imgSnsButton: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button01_m.jpg',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button01.jpg',
|
||||
},
|
||||
tracking: {
|
||||
click_item: 'imgSnsButton_7. 사전등록-SNS버튼이미지(1)',
|
||||
action_type: 'click',
|
||||
click_sarea: 'promotionPreregist_tmpl_01__imgSnsButton',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button02_m.jpg',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button02.jpg',
|
||||
},
|
||||
tracking: {
|
||||
click_item: 'imgSnsButton_7. 사전등록-SNS버튼이미지(2)',
|
||||
action_type: 'click',
|
||||
click_sarea: 'promotionPreregist_tmpl_01__imgSnsButton',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
imgSnsReward: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward_sns_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward_sns.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
subTitleAccReward: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '이벤트 기간 + 2024.06.04 ~ 정식 오픈 전까지',
|
||||
color_code: '#c5902f',
|
||||
color_name: '',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
imgPreregistReward: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
mainTitleAccReward: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '카카오톡 공식 채널 구독 이벤트',
|
||||
color_code: '#c5902f',
|
||||
color_name: '',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
backgroundAccReward: {
|
||||
groups: [
|
||||
{
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg_acc_reward_m.jpg',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg_acc_reward.jpg',
|
||||
},
|
||||
resource_type: 'IMG_COMM',
|
||||
},
|
||||
],
|
||||
},
|
||||
descriptionAccReward: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '※ 달성 여부는 실시간으로 반영되지 않을 수 있습니다.',
|
||||
color_code: '#737474',
|
||||
color_name: '',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
isAccRewardCompleted: {},
|
||||
preregistButtonColor: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
color_code: '#cc0000',
|
||||
color_name: '',
|
||||
},
|
||||
resource_type: 'COLOR',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
color_code: '#ccff00',
|
||||
color_name: '',
|
||||
},
|
||||
resource_type: 'COLOR',
|
||||
},
|
||||
],
|
||||
},
|
||||
rewardTitleAccReward: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '누적 목표를 달성할수록 더 많은 보상을 드립니다!',
|
||||
color_code: '#33312e',
|
||||
color_name: '',
|
||||
},
|
||||
resource_type: 'TXT',
|
||||
},
|
||||
],
|
||||
},
|
||||
imgAccRewardIncomplete: {
|
||||
groups: [
|
||||
{
|
||||
display: {
|
||||
text: '골드 100,000',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete01_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete01.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '중급 물약 x100',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete02_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete02.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '방어구 강화석 x3',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete03_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete03.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '무기 강화석 x3',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete04_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete04.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
{
|
||||
display: {
|
||||
text: '순수한 무기 강화석 x1',
|
||||
},
|
||||
res_path: {
|
||||
path_mo:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete05_m.png',
|
||||
path_pc:
|
||||
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete05.png',
|
||||
},
|
||||
resource_type: 'IMG_LANG',
|
||||
},
|
||||
],
|
||||
},
|
||||
} as any
|
||||
const { locale } = useI18n()
|
||||
const { getOperateResourcesData } = useResourcesData()
|
||||
const { gameData } = storeToRefs(useGameDataStore())
|
||||
const { pageData } = storeToRefs(usePageDataStore())
|
||||
|
||||
// Constants
|
||||
const PREREGIST_PLATFORMS = [
|
||||
{ platform: 'stove', label: '사전 등록 하기' },
|
||||
{ platform: 'google_play', label: '사전 등록 하기' },
|
||||
{ platform: 'app_store', label: '사전 등록 하기' },
|
||||
] as const
|
||||
const COLOR_INDEX = { BACKGROUND: 0, TEXT: 1 } as const
|
||||
const OS_TYPE_MAP: Record<string, Platform[]> = {
|
||||
'1': ['google_play'],
|
||||
'2': ['app_store'],
|
||||
'3': ['google_play', 'app_store'],
|
||||
}
|
||||
|
||||
const COLOR_INDEX = {
|
||||
BACKGROUND: 0,
|
||||
TEXT: 1,
|
||||
} as const
|
||||
const preregistModalRef = ref<{ handlePreregist: () => void } | null>(null)
|
||||
|
||||
// Preregist Section
|
||||
const backgroundData = computed(() =>
|
||||
const preregistCode = computed(
|
||||
() => getComponentGroup(props.components, 'preregistCode')?.display?.text
|
||||
)
|
||||
const prdBackgroundData = computed(() =>
|
||||
getComponentGroup(props.components, 'background')
|
||||
)
|
||||
const mainTitleData = computed(() =>
|
||||
const preMainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitle')
|
||||
)
|
||||
const subTitleData = computed(() =>
|
||||
const preSubTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'subTitle')
|
||||
)
|
||||
const imgPreregistRewardData = computed(() =>
|
||||
const preImgPreregistdData = computed(() =>
|
||||
getComponentGroup(props.components, 'imgPreregistReward')
|
||||
)
|
||||
const imgSnsRewardData = computed(() =>
|
||||
const preImgSnsData = computed(() =>
|
||||
getComponentGroup(props.components, 'imgSnsReward')
|
||||
)
|
||||
const preregistButtonColorData = computed(() =>
|
||||
getComponentGroupAry(props.components, 'preregistButtonColor')
|
||||
)
|
||||
const imgSnsButtonData = computed(() =>
|
||||
getComponentGroupAry(props.components, 'imgSnsButton')
|
||||
)
|
||||
const txtSnsLinkData = computed(() =>
|
||||
getComponentGroupAry(props.components, 'txtSnsLink')
|
||||
)
|
||||
const descriptionData = computed(() =>
|
||||
const preDescriptionData = computed(() =>
|
||||
getComponentGroup(props.components, 'description')
|
||||
)
|
||||
const snsButtons = computed(() => {
|
||||
const buttons = imgSnsButtonData.value
|
||||
const links = txtSnsLinkData.value
|
||||
// SNS Buttons
|
||||
const snsButtonsData = computed(() => {
|
||||
const buttons = getComponentGroupAry(props.components, 'imgSnsButton')
|
||||
const links = getComponentGroupAry(props.components, 'txtSnsLink')
|
||||
|
||||
if (!buttons?.length) return []
|
||||
|
||||
return buttons.map((button, index) => ({
|
||||
image: button,
|
||||
link: links?.[index]?.display?.text ?? '',
|
||||
id: button.id ?? `sns-${index}`,
|
||||
}))
|
||||
})
|
||||
const buttonColors = computed(() => {
|
||||
const colorData = preregistButtonColorData.value
|
||||
|
||||
if (!colorData?.length) {
|
||||
return { background: undefined, text: undefined }
|
||||
}
|
||||
// Button Colors
|
||||
const buttonColors = computed(() => {
|
||||
const colorData = getComponentGroupAry(
|
||||
props.components,
|
||||
'preregistButtonColor'
|
||||
)
|
||||
|
||||
if (!colorData?.length)
|
||||
return { backgroundColor: undefined, textColor: undefined }
|
||||
|
||||
return {
|
||||
background: getColorCode({
|
||||
backgroundColor: getColorCode({
|
||||
colorName: colorData[COLOR_INDEX.BACKGROUND]?.display?.color_name,
|
||||
colorCode: colorData[COLOR_INDEX.BACKGROUND]?.display?.color_code,
|
||||
}),
|
||||
text: getColorCode({
|
||||
textColor: getColorCode({
|
||||
colorName: colorData[COLOR_INDEX.TEXT]?.display?.color_name,
|
||||
colorCode: colorData[COLOR_INDEX.TEXT]?.display?.color_code,
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
// Platform Buttons
|
||||
const platformButtons = computed<Platform[]>(() => {
|
||||
const osType = String(gameData.value?.os_type ?? '')
|
||||
return OS_TYPE_MAP[osType] ?? []
|
||||
})
|
||||
|
||||
// Reward Section
|
||||
const backgroundAccRewardData = computed(() =>
|
||||
const accBackgroundData = computed(() =>
|
||||
getComponentGroup(props.components, 'backgroundAccReward')
|
||||
)
|
||||
const mainTitleAccRewardData = computed(() =>
|
||||
const accMainTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'mainTitleAccReward')
|
||||
)
|
||||
const subTitleAccRewardData = computed(() =>
|
||||
const accSubTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'subTitleAccReward')
|
||||
)
|
||||
const rewardTitleAccRewardData = computed(() =>
|
||||
const accRewardTitleData = computed(() =>
|
||||
getComponentGroup(props.components, 'rewardTitleAccReward')
|
||||
)
|
||||
const imgAccRewardData = computed(() =>
|
||||
getComponentGroupAry(test, 'imgAccReward')
|
||||
)
|
||||
const imgAccRewardLength = computed(() => imgAccRewardData.value?.length ?? 0)
|
||||
const descriptionAccRewardData = computed(() =>
|
||||
const accDescriptionData = computed(() =>
|
||||
getComponentGroup(props.components, 'descriptionAccReward')
|
||||
)
|
||||
const accPaginationData = computed(() =>
|
||||
getComponentGroupAry(props.components, 'pagination')
|
||||
)
|
||||
|
||||
// Async Data - 리워드 완료 데이터
|
||||
const { data: rewardCompletedData } = await useAsyncData(
|
||||
`fx-preregist-resources-${pageData.value?.page_seq}-${pageData.value?.page_ver}-${props.pageVerTmplSeq}`,
|
||||
async () => {
|
||||
const { page_seq, page_ver } = pageData.value ?? {}
|
||||
|
||||
if (!page_seq || !page_ver) return []
|
||||
|
||||
try {
|
||||
const operateGroupList = await getOperateResourcesData({
|
||||
pageSeq: page_seq,
|
||||
pageVer: page_ver,
|
||||
pageVerTmplSeq: props.pageVerTmplSeq,
|
||||
langCode: locale.value,
|
||||
})
|
||||
|
||||
return getComponentContainer(operateGroupList, 'isAccRewardCompleted', {
|
||||
isGroup: true,
|
||||
}) as OperateGroupItem[]
|
||||
} catch (error) {
|
||||
if (import.meta.dev) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[FxPreregist01] Failed to fetch reward data:', error)
|
||||
}
|
||||
return []
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => [],
|
||||
server: false,
|
||||
}
|
||||
)
|
||||
|
||||
// Reward Images
|
||||
const rewardImages = computed(() => {
|
||||
const defaultList = getComponentGroupAry(props.components, 'imgAccReward')
|
||||
const incompleteList = getComponentGroupAry(
|
||||
props.components,
|
||||
'imgAccRewardIncomplete'
|
||||
)
|
||||
|
||||
if (!defaultList?.length) return []
|
||||
|
||||
return defaultList.map((defaultItem, index) => ({
|
||||
id: defaultItem.id ?? `reward-${index}`,
|
||||
default: defaultItem,
|
||||
incomplete: incompleteList?.[index] ?? null,
|
||||
flagType: rewardCompletedData.value?.[index]?.flag_type ?? 0,
|
||||
}))
|
||||
})
|
||||
|
||||
// Splide Options
|
||||
const splideOptions = computed(() => {
|
||||
const length = rewardImages.value.length
|
||||
|
||||
return {
|
||||
type: 'slide',
|
||||
type: 'slide' as const,
|
||||
gap: 16,
|
||||
arrows: false,
|
||||
pagination: false,
|
||||
destroy: true,
|
||||
breakpoints: {
|
||||
[BREAKPOINTS.md - 1]: {
|
||||
destroy: imgAccRewardLength.value <= 3,
|
||||
perPage: 'auto',
|
||||
focus: 'center',
|
||||
drag: imgAccRewardLength.value > 3,
|
||||
padding: {
|
||||
left: 40,
|
||||
right: 40,
|
||||
},
|
||||
937: {
|
||||
destroy: length < 5,
|
||||
gap: 12,
|
||||
padding: { left: 40, right: 40 },
|
||||
},
|
||||
[BREAKPOINTS.sm - 1]: {
|
||||
padding: { left: 20, right: 20 },
|
||||
},
|
||||
723: {
|
||||
destroy: length < 4,
|
||||
},
|
||||
561: {
|
||||
destroy: false,
|
||||
gap: 12,
|
||||
drag: true,
|
||||
padding: {
|
||||
left: 20,
|
||||
right: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// Handler
|
||||
const handlePreregistClick = () => {
|
||||
preregistModalRef.value?.handlePreregist()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="relative py-[80px] md:py-[120px]">
|
||||
<WidgetsBackground v-if="backgroundData" :resources-data="backgroundData" />
|
||||
<div class="content-standard">
|
||||
<WidgetsMainTitle
|
||||
v-if="mainTitleData"
|
||||
:resources-data="mainTitleData"
|
||||
class="title-xlg"
|
||||
<div class="section-container">
|
||||
<!-- Preregist Section -->
|
||||
<section class="relative py-[80px] md:py-[120px]">
|
||||
<WidgetsBackground
|
||||
v-if="prdBackgroundData"
|
||||
:resources-data="prdBackgroundData"
|
||||
/>
|
||||
<WidgetsSubTitle
|
||||
v-if="subTitleData"
|
||||
:resources-data="subTitleData"
|
||||
class="title-sm mt-2"
|
||||
/>
|
||||
<div class="flex flex-col gap-4 mt-8 md:flex-row">
|
||||
<div v-if="imgPreregistRewardData" class="w-full max-w-[446px]">
|
||||
<AtomsImg
|
||||
:src="getImagePaths(imgPreregistRewardData)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="imgSnsRewardData" class="relative w-full max-w-[446px]">
|
||||
<AtomsImg
|
||||
:src="getImagePaths(imgSnsRewardData)"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="w-full h-full object-contain"
|
||||
/>
|
||||
<ul
|
||||
v-if="snsButtons.length"
|
||||
class="absolute bottom-[20px] left-0 w-full flex items-center justify-center gap-2 md:bottom-[24px] md:gap-3"
|
||||
>
|
||||
<li
|
||||
v-for="(snsButton, index) in snsButtons"
|
||||
:key="`sns-${snsButton.link}-${index}`"
|
||||
>
|
||||
<a
|
||||
:href="snsButton.link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<AtomsImg :src="getImagePaths(snsButton.image)" />
|
||||
<span class="sr-only">
|
||||
{{ snsButton.link }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="PREREGIST_PLATFORMS.length"
|
||||
class="flex gap-3 justify-center flex-wrap mt-8 md:gap-2.5"
|
||||
>
|
||||
<AtomsButtonLauncher
|
||||
v-for="item in PREREGIST_PLATFORMS"
|
||||
:key="`preregist-${item.platform}`"
|
||||
type="duplication"
|
||||
:platform="item.platform"
|
||||
:background-color="buttonColors.background"
|
||||
:text-color="buttonColors.text"
|
||||
>
|
||||
{{ item.label }}
|
||||
</AtomsButtonLauncher>
|
||||
</div>
|
||||
<WidgetsDescription
|
||||
v-if="descriptionData"
|
||||
:resources-data="descriptionData"
|
||||
class="mt-8"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<section class="relative py-[80px] md:py-[120px]">
|
||||
<WidgetsBackground
|
||||
v-if="backgroundAccRewardData"
|
||||
:resources-data="backgroundAccRewardData"
|
||||
/>
|
||||
<div class="content-standard">
|
||||
<WidgetsMainTitle
|
||||
v-if="mainTitleAccRewardData"
|
||||
:resources-data="mainTitleAccRewardData"
|
||||
class="title-xlg"
|
||||
/>
|
||||
<WidgetsSubTitle
|
||||
v-if="subTitleAccRewardData"
|
||||
:resources-data="subTitleAccRewardData"
|
||||
class="title-sm mt-2"
|
||||
/>
|
||||
<WidgetsSubTitle
|
||||
v-if="rewardTitleAccRewardData"
|
||||
tag="h4"
|
||||
:resources-data="rewardTitleAccRewardData"
|
||||
class="mt-[48px] text-[18px] font-[700] leading-[26px] tracking-[-0.54px] drop-shadow-[0_2px_2px_rgba(0,0,0,0.6)] md:mt-[72px] md:text-[24px] md:leading-[34px] md:tracking-[0.72px]"
|
||||
/>
|
||||
<div v-if="imgAccRewardLength" class="mt-6 md:mt-8">
|
||||
<ul class="hidden md:flex justify-center md:mb-[20px]">
|
||||
<li
|
||||
v-for="index in imgAccRewardLength"
|
||||
:key="index"
|
||||
class="flex items-center"
|
||||
>
|
||||
<span class="progress-bullet"></span>
|
||||
<div v-if="index !== imgAccRewardLength" class="progress-bar">
|
||||
<span class="progress-fill"></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<BlocksSlideDefault
|
||||
v-bind="splideOptions"
|
||||
class="w-[100vw] mx-[-20px] sm:mx-[-40px] md:w-auto md:mx-auto"
|
||||
>
|
||||
<SplideSlide
|
||||
v-for="(item, index) in imgAccRewardData"
|
||||
:key="`reward-${item.id ?? index}`"
|
||||
class="w-[162px] h-[228px] md:w-[176px] md:h-[249px]"
|
||||
>
|
||||
<div class="content-standard">
|
||||
<WidgetsMainTitle
|
||||
v-if="preMainTitleData"
|
||||
:resources-data="preMainTitleData"
|
||||
class="title-xlg"
|
||||
/>
|
||||
<WidgetsSubTitle
|
||||
v-if="preSubTitleData"
|
||||
:resources-data="preSubTitleData"
|
||||
class="title-sm mt-2"
|
||||
/>
|
||||
<div class="flex flex-col gap-4 mt-8 md:flex-row">
|
||||
<div v-if="preImgPreregistdData" class="w-full max-w-[446px]">
|
||||
<AtomsImg
|
||||
:src="getImagePaths(item)"
|
||||
:alt="item?.display?.text ?? `Reward ${index + 1}`"
|
||||
:src="getImagePaths(preImgPreregistdData)"
|
||||
:alt="preImgPreregistdData?.display?.text"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="w-full h-full object-contain"
|
||||
/>
|
||||
</SplideSlide>
|
||||
</BlocksSlideDefault>
|
||||
</div>
|
||||
<div v-if="preImgSnsData" class="relative w-full max-w-[446px]">
|
||||
<AtomsImg
|
||||
:src="getImagePaths(preImgSnsData)"
|
||||
:alt="preImgSnsData?.display?.text"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="w-full h-full object-contain"
|
||||
/>
|
||||
<ul
|
||||
v-if="snsButtonsData.length"
|
||||
class="absolute bottom-[20px] left-0 w-full flex items-center justify-center gap-2 md:bottom-[24px] md:gap-3"
|
||||
>
|
||||
<li
|
||||
v-for="btn in snsButtonsData"
|
||||
:key="btn.id"
|
||||
class="w-[48px] h-[40px] md:w-[72px] md:h-[56px]"
|
||||
>
|
||||
<a :href="btn.link" target="_blank" rel="noopener noreferrer">
|
||||
<AtomsImg
|
||||
:src="getImagePaths(btn.image)"
|
||||
:alt="btn.image?.display?.text"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-3 justify-center flex-wrap mt-8 md:gap-2.5">
|
||||
<AtomsButtonLauncher
|
||||
type="duplication"
|
||||
platform="stove"
|
||||
:background-color="buttonColors.backgroundColor"
|
||||
:text-color="buttonColors.textColor"
|
||||
@click="handlePreregistClick"
|
||||
>
|
||||
사전 등록 하기
|
||||
</AtomsButtonLauncher>
|
||||
<AtomsButtonLauncher
|
||||
v-for="platform in platformButtons"
|
||||
:key="`preregist-${platform}`"
|
||||
type="duplication"
|
||||
:platform="platform"
|
||||
:background-color="buttonColors.backgroundColor"
|
||||
:text-color="buttonColors.textColor"
|
||||
>
|
||||
사전 등록 하기
|
||||
</AtomsButtonLauncher>
|
||||
</div>
|
||||
<WidgetsDescription
|
||||
v-if="preDescriptionData"
|
||||
:resources-data="preDescriptionData"
|
||||
class="mt-8"
|
||||
/>
|
||||
</div>
|
||||
<WidgetsDescription
|
||||
v-if="descriptionAccRewardData"
|
||||
:resources-data="descriptionAccRewardData"
|
||||
class="mt-6 md:mt-8"
|
||||
</section>
|
||||
<!-- Reward Section -->
|
||||
<section class="relative py-[80px] md:py-[120px]">
|
||||
<WidgetsBackground
|
||||
v-if="accBackgroundData"
|
||||
:resources-data="accBackgroundData"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
<div class="content-standard">
|
||||
<WidgetsMainTitle
|
||||
v-if="accMainTitleData"
|
||||
:resources-data="accMainTitleData"
|
||||
class="title-xlg"
|
||||
/>
|
||||
<WidgetsSubTitle
|
||||
v-if="accSubTitleData"
|
||||
:resources-data="accSubTitleData"
|
||||
class="title-sm mt-2"
|
||||
/>
|
||||
<WidgetsSubTitle
|
||||
v-if="accRewardTitleData"
|
||||
tag="h4"
|
||||
:resources-data="accRewardTitleData"
|
||||
class="mt-[48px] text-[18px] font-[700] leading-[26px] tracking-[-0.54px] drop-shadow-[0_2px_2px_rgba(0,0,0,0.6)] md:mt-[72px] md:text-[24px] md:leading-[34px] md:tracking-[0.72px]"
|
||||
/>
|
||||
<div
|
||||
v-if="rewardImages.length"
|
||||
class="overflow-hidden w-[calc(100%+40px)] min-h-[228px] mt-6 mx-[-20px] sm:w-[calc(100%+80px)] sm:mx-[-40px] md:w-full md:min-h-[281px] md:mt-8 md:mx-auto"
|
||||
>
|
||||
<ClientOnly>
|
||||
<ul
|
||||
class="hidden md:flex justify-center md:mb-[20px]"
|
||||
:style="getPaginationClass(accPaginationData)"
|
||||
>
|
||||
<li
|
||||
v-for="(item, index) in rewardImages"
|
||||
:key="item.id"
|
||||
:class="[
|
||||
'flex items-center',
|
||||
{ 'is-completed': item.flagType === 1 },
|
||||
]"
|
||||
>
|
||||
<span class="progress-bullet"></span>
|
||||
<div
|
||||
v-if="index < rewardImages.length - 1"
|
||||
class="progress-bar"
|
||||
></div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<BlocksSlideDefault v-bind="splideOptions">
|
||||
<SplideSlide
|
||||
v-for="item in rewardImages"
|
||||
:key="item.id"
|
||||
class="w-[162px] h-[228px] md:w-[176px] md:h-[249px]"
|
||||
>
|
||||
<AtomsImg
|
||||
:src="
|
||||
getImagePaths(
|
||||
item.flagType === 1 ? item.incomplete : item.default
|
||||
)
|
||||
"
|
||||
:alt="item.default?.display?.text"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
class="w-full h-full object-contain"
|
||||
/>
|
||||
</SplideSlide>
|
||||
</BlocksSlideDefault>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
<WidgetsDescription
|
||||
v-if="accDescriptionData"
|
||||
:resources-data="accDescriptionData"
|
||||
class="mt-6 md:mt-8"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<WidgetsModalPreregist
|
||||
ref="preregistModalRef"
|
||||
:preregist-code="preregistCode"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -612,16 +373,14 @@ const splideOptions = computed(() => {
|
||||
|
||||
.progress-bullet {
|
||||
@apply block w-3 h-3 rounded-full transition-all duration-300;
|
||||
background-color: red;
|
||||
/* background-color: var(--pagination-disabled); */
|
||||
background-color: var(--pagination-disabled);
|
||||
}
|
||||
.progress-bar {
|
||||
@apply relative w-[180px] h-0.5 overflow-hidden;
|
||||
/* background-color: var(--pagination-disabled); */
|
||||
background-color: red;
|
||||
@apply w-[180px] h-0.5 overflow-hidden;
|
||||
background-color: var(--pagination-disabled);
|
||||
}
|
||||
.progress-fill {
|
||||
@apply absolute inset-y-0 left-0 w-[0];
|
||||
.is-completed .progress-bullet,
|
||||
.is-completed .progress-bar {
|
||||
background-color: var(--pagination-active);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user