Files
web-temp/app/pages/inspection/index.vue

383 lines
10 KiB
Vue

<template>
<header class="header">
<BlocksStoveGnb class="min-h-[48px]" />
</header>
<section class="inspection-section">
<clientOnly>
<!-- 로고 -->
<div class="inspection-logo">
<img
:src="logoImgUrl"
alt="logo"
class="w-full h-full object-contain"
/>
</div>
<div class="inspection-content">
<!-- 점검 메시지 -->
<h1 class="inspection-title text-lg md:text-2xl">
{{ tm('Inspection_Now_Maintenance') }}
</h1>
<div class="inspection-cards">
<!-- 점검 시간 카드 -->
<div
v-if="webInspectionData"
class="inspection-card inspection-time-card"
>
<h2 class="card-title text-base text-md md:text-lg">
{{ tm('Inspection_Maintenance_Time') }}
</h2>
<div class="inspection-time text-sm md:text-base font-medium">
<div
v-dompurify-html="getLocaleTimezone()"
class="time-row"
></div>
</div>
</div>
<!-- 온스토브 & 다운로드 카드 -->
<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')"
class="block text-left"
></span>
</h3>
<div class="button-group justify-center">
<AtomsButton
variant="outlined"
class="flex-1 size-extra-small md:size-small !px-0"
@click="handleCommunityClick"
>
<span class="text">{{ tm('Inspection_Community_Btn') }}</span>
<AtomsIconsLongArrowRightLine :size="16" color="#1F1F1F" />
</AtomsButton>
<BlocksButtonLauncher
v-if="launchingStatus"
type="single"
platform="pc"
class="inspection-launcher"
>
{{ tm('Txt_Game_Start') }}
<AtomsIconsPlayRoundFill :size="16" color="#332C2A" />
</BlocksButtonLauncher>
</div>
</div>
<!-- 다운로드 카드 -->
<div
v-if="launchingStatus && supportedPlatforms.length > 0"
class="inspection-card inspection-download-card"
>
<h3 class="card-title text-base md:text-lg">
{{
t('Inspection_Txt_Download', {
gameName: gameName,
})
}}
</h3>
<div class="flex flex-row gap-3 flex-wrap">
<template
v-for="Platform in supportedPlatforms"
:key="Platform"
>
<BlocksButtonLauncher
:type="Platform === 'pc' ? 'default' : 'single'"
variant="outlined"
:platform="Platform"
:class="[
getButtonText(Platform) ? 'flex-1' : 'no-text',
'size-extra-small md:size-small',
]"
>
{{ getButtonText(Platform) }}
</BlocksButtonLauncher>
</template>
</div>
</div>
</div>
</div>
</div>
</clientOnly>
</section>
</template>
<script setup lang="ts">
import { globalDateFormat } from '@seed-next/date'
import AtomsIconsPlayRoundFill from '#layers/components/atoms/icons/PlayRoundFill.vue'
import type { PlatformTransformType } from '#layers/types/api/gameData'
// SEO: Prevent search engine indexing of inspection pages
useSeoMeta({
robots: 'noindex, nofollow',
})
const config = useRuntimeConfig()
const stoveApiUrl = config.public.stoveApiUrl as string
const dataResourcesUrl = config.public.dataResourcesUrl as string
const multilingualFileName = 'STOVE_PUBTEMPLATE_homepage_brand_inspection.json'
// Multilingual
const resultGetMultilingual = await useGetMultilingual({
baseApiUrl: dataResourcesUrl,
fileName: multilingualFileName,
})
const { t, tm, locale }: any = useI18n({
useScope: 'local',
messages: Object(resultGetMultilingual?.value?.multilingual),
})
const device = useDevice()
const loadingStore = useLoadingStore()
const { webInspectionData, getInspectionDataExternal } =
useGetInspectionDataExternal()
const gameDataStore = useGameDataStore()
const { gameId, gameName, platformType, osType } = storeToRefs(gameDataStore)
await getInspectionDataExternal({
baseApiUrl: stoveApiUrl,
gameId: gameId.value,
})
const TIMEZONE_MAP: Record<string, string> = {
ko: 'KST',
en: 'UTC',
ja: 'JST',
'zh-tw': '台灣時間',
'zh-cn': 'CST',
th: 'ICT',
}
const DEFAULT_TIMEZONE = 'KST'
const formatInspectionDate = (date: number | Date) => {
const currentLocale = locale.value
const nation = currentLocale === 'ko' ? 'KR' : ''
return `${globalDateFormat(date, currentLocale, nation, { useFullDate: true })}`
}
const formatInspectionUtc = (date: number) =>
`${globalDateFormat(date, 'en', '', {
useFullDate: true,
useUtc: true,
})}`
// locale에 따라 뒤에 KST 또는 UTC 등을 추가
const getLocaleTimezone = () => {
const tsStartDate = webInspectionData.value?.ts_start_date || 0
const tsEndDate = webInspectionData.value?.ts_end_date || 0
const currentLocale = locale.value
const timezone = TIMEZONE_MAP[currentLocale] ?? DEFAULT_TIMEZONE
const localTime = `${formatInspectionDate(
new Date(tsStartDate)
)} <br class="md:hidden">~ ${formatInspectionDate(
new Date(tsEndDate)
)} (${timezone})`
const utcTime = `${formatInspectionUtc(
tsStartDate
)} <br class="md:hidden">~ ${formatInspectionUtc(tsEndDate)} (UTC)`
return currentLocale === 'en' ? localTime : `${localTime}<br>${utcTime}`
}
const launchingStatus = computed(() => {
return webInspectionData.value?.launching_status
})
const supportedPlatforms = computed(() => {
const basePlatforms = getSupportedPlatforms(
platformType.value,
osType.value
) as PlatformTransformType[]
// 데스크탑 환경에서는 모든 플랫폼 표시
if (device.isDesktop) {
return basePlatforms
}
// 모바일 환경에서는 pc 버튼 제거
let platforms = basePlatforms.filter(platform => platform !== 'pc')
// AOS 에서는 app_store 제거
if (device.isAndroid) {
platforms = platforms.filter(platform => platform !== 'app_store')
}
// iOS 에서는 google_play 제거
if (device.isApple) {
platforms = platforms.filter(platform => platform !== 'google_play')
}
return platforms
})
const logoImgUrl = computed(() => {
const currentLocale = locale.value || 'ko'
const localeData = (webInspectionData.value as any)?.[currentLocale]
return formatPathHost(localeData?.img_json?.bi_large)
})
const communityUrl = computed(() => {
const currentLocale = locale.value || 'ko'
const localeData = (webInspectionData.value as any)?.[currentLocale]
return localeData?.url_json?.community
})
const handleCommunityClick = () => {
window.open(communityUrl.value, '_blank')
}
const PLATFORM_LABEL_KEYS: Record<PlatformTransformType, string> = {
pc: 'platform_pc',
google_play: 'platform_google_play',
app_store: 'platform_app_store',
}
const getButtonText = (platform: PlatformTransformType) => {
// 데스크탭 환경에서 pc지원하는 경우 os 버튼 텍스트 미표시
const isDesktopWithSinglePlatform =
device.isDesktop && platformType.value !== '2' && platform !== 'pc'
if (isDesktopWithSinglePlatform) {
return ''
}
const key = PLATFORM_LABEL_KEYS[platform]
return key ? tm(key) : ''
}
onMounted(() => {
loadingStore.stopFullLoading()
})
definePageMeta({
middleware: ['inspection'],
layout: 'only-stove',
})
</script>
<style scoped>
.inspection-section {
@apply flex flex-col items-center gap-10 px-10 py-[120px] pb-[200px] min-h-[calc(100vh-48px)];
background-color: #f0f0f0;
}
.inspection-logo {
@apply w-[944px] h-[50px] flex-shrink-0;
}
.inspection-logo img {
@apply w-full h-full object-contain;
}
.inspection-content {
@apply flex flex-col items-center gap-10 w-full max-w-[944px];
}
.inspection-title {
@apply text-center font-bold tracking-[-0.72px] text-[#1F1F1F];
}
.inspection-cards {
@apply flex flex-col gap-5 w-full;
}
.inspection-card {
@apply bg-white rounded-2xl px-4 py-6 md:p-8;
}
.inspection-time-card {
@apply flex flex-col items-center gap-4;
}
.card-title {
@apply text-center leading-[30px] font-bold tracking-[-0.6px] text-[#1F1F1F];
}
.inspection-time {
@apply flex flex-col items-center gap-0 md:gap-2;
}
.time-row {
@apply text-center leading-[26px] font-medium tracking-[-0.48px] text-[#1F1F1F];
}
.inspection-bottom-cards {
@apply flex flex-row gap-5 w-full;
}
.inspection-stove-card,
.inspection-download-card {
@apply flex flex-col justify-between gap-4 flex-1;
}
.inspection-stove-card .card-title {
@apply leading-[26px] font-bold tracking-[-0.54px] text-[#1F1F1F];
}
.inspection-download-card .card-title {
@apply text-left leading-[26px] font-bold tracking-[-0.54px] text-[#1F1F1F];
}
.inspection-content-text {
@apply text-left leading-[26px] font-medium tracking-[-0.48px] text-[#1F1F1F];
white-space: pre-line;
}
.button-group {
@apply flex flex-row gap-3;
}
@media (max-width: 1024px) {
.inspection-section {
@apply px-5 py-20 pb-32;
}
.inspection-logo {
@apply w-full max-w-[944px];
}
.inspection-time-card {
@apply w-full;
}
.inspection-bottom-cards {
@apply flex-col;
}
.inspection-stove-card,
.inspection-download-card {
@apply w-full;
}
}
.inspection-download-card .btn-platform-pc {
@apply w-auto flex-1;
}
.button-group:deep(.btn-base .text) {
@apply mr-[2px] md:mr-[4px] text-[#1F1F1F];
}
.button-group:deep(.inspection-launcher.btn-base) {
@apply flex-1 bg-[var(--primary)] px-0 rounded md:rounded-lg;
}
.button-group:deep(.inspection-launcher) .text {
@apply flex items-center justify-center gap-[2px] mr-0 md:gap-[4px];
}
.button-group:deep(.inspection-launcher.btn-base .icon-platform) {
@apply hidden;
}
</style>