fix. 사전등록 로직 수정
This commit is contained in:
@@ -1,35 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
import { PREREGIST_ERROR_CODE } from '#layers/composables/usePreregist'
|
||||
|
||||
interface Props {
|
||||
preregistCode?: string
|
||||
tm?: any // i18n translate message function
|
||||
tm?: (key: string) => string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// Composables
|
||||
const { locale } = useI18n()
|
||||
const device = useDevice()
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const gameDataStore = useGameDataStore()
|
||||
const modalStore = useModalStore()
|
||||
const { handleTokenValidation } = useTokenValidation()
|
||||
const { getPreregist, setPreregist } = usePreregist()
|
||||
const { isNorthAmerica, countryCode } = useGds()
|
||||
const {
|
||||
countryCode,
|
||||
preregistDate,
|
||||
checkCountryByIp,
|
||||
getPreregist,
|
||||
setPreregist,
|
||||
} = usePreregist()
|
||||
|
||||
const { gameData } = storeToRefs(gameDataStore)
|
||||
|
||||
// Constants
|
||||
const stoveCs = runtimeConfig.public.stoveCs
|
||||
const customerServiceUrl = `${stoveCs}/${gameData.value?.game_id}`
|
||||
|
||||
// Props로 전달받은 tm 또는 전역 i18n의 tm 사용
|
||||
const t = (key: string) => {
|
||||
if (props.tm) {
|
||||
return props.tm(key)
|
||||
}
|
||||
return key
|
||||
/**
|
||||
* 번역 함수 (Props로 전달받은 tm 또는 key 반환)
|
||||
*/
|
||||
const tm = (key: string): string => {
|
||||
return props.tm?.(key) ?? key
|
||||
}
|
||||
|
||||
// 게임명 치환 헬퍼
|
||||
const tWithGameName = (key: string) => {
|
||||
const text = t(key)
|
||||
const isModalOpen = ref(false)
|
||||
const currentStep = ref<1 | 2>(1)
|
||||
const isSubmitting = ref(false)
|
||||
const isCheckedMarketing = ref(false)
|
||||
const isExpandedMarketing = ref(false)
|
||||
const isValidated = ref(false) // 검증 완료 여부 (중복 검증 방지)
|
||||
|
||||
const canSubmit = computed(() => isCheckedMarketing.value)
|
||||
const errorMessages = computed<Record<number, string>>(() => ({
|
||||
[PREREGIST_ERROR_CODE.NOT_PERIOD]: tm('Preregist_Alert_Date'),
|
||||
[PREREGIST_ERROR_CODE.REQUIRED_TERMS]: tm('Preregist_Alert_Agree'),
|
||||
[PREREGIST_ERROR_CODE.AGE_RESTRICTION]: tm('Preregist_Alert_Age'),
|
||||
[PREREGIST_ERROR_CODE.ALREADY_REGISTERED]: tm('Preregist_Alert_Already'),
|
||||
}))
|
||||
|
||||
const tmWithGameName = (key: string): string => {
|
||||
const text = tm(key)
|
||||
if (typeof text === 'string' && text.includes('%게임명%')) {
|
||||
const gameName = gameData.value?.game_name ?? ''
|
||||
return text.replace(/%게임명%/g, gameName)
|
||||
@@ -37,111 +60,64 @@ const tWithGameName = (key: string) => {
|
||||
return text
|
||||
}
|
||||
|
||||
// State
|
||||
const isOpen = ref(false)
|
||||
const step = ref<1 | 2>(1)
|
||||
const isSubmitting = ref(false)
|
||||
|
||||
const checks = ref({
|
||||
age: false,
|
||||
privacy: false,
|
||||
marketing: false,
|
||||
})
|
||||
const birthdate = ref({
|
||||
month: '',
|
||||
day: '',
|
||||
year: '',
|
||||
})
|
||||
const expanded = ref({
|
||||
privacy: false,
|
||||
marketing: false,
|
||||
})
|
||||
|
||||
const currentYear = new Date().getFullYear()
|
||||
|
||||
const currentDate = computed(() => new Date().toISOString().split('T')[0])
|
||||
const allChecked = computed(() => {
|
||||
const { age, privacy, marketing } = checks.value
|
||||
return isNorthAmerica.value
|
||||
? privacy && marketing
|
||||
: age && privacy && marketing
|
||||
})
|
||||
const isBirthdateValid = computed(() => {
|
||||
if (!isNorthAmerica.value) return true
|
||||
|
||||
const { month, day, year } = birthdate.value
|
||||
if (!month || !day || !year) return false
|
||||
|
||||
const monthNum = Number(month)
|
||||
const dayNum = Number(day)
|
||||
const yearNum = Number(year)
|
||||
|
||||
return (
|
||||
monthNum >= 1 &&
|
||||
monthNum <= 12 &&
|
||||
dayNum >= 1 &&
|
||||
dayNum <= 31 &&
|
||||
yearNum >= 1900 &&
|
||||
yearNum <= currentYear
|
||||
)
|
||||
})
|
||||
const canSubmit = computed(() => {
|
||||
const { age, privacy, marketing } = checks.value
|
||||
if (!privacy || !marketing) return false
|
||||
|
||||
return isNorthAmerica.value ? isBirthdateValid.value : age
|
||||
})
|
||||
|
||||
const handleCheckAll = () => {
|
||||
const newValue = !allChecked.value
|
||||
checks.value = {
|
||||
age: isNorthAmerica.value ? false : newValue,
|
||||
privacy: newValue,
|
||||
marketing: newValue,
|
||||
}
|
||||
const toggleMarketing = () => {
|
||||
isCheckedMarketing.value = !isCheckedMarketing.value
|
||||
}
|
||||
const handleCheck = (key: keyof typeof checks.value) => {
|
||||
checks.value[key] = !checks.value[key]
|
||||
}
|
||||
const toggleExpand = (key: keyof typeof expanded.value, event: Event) => {
|
||||
|
||||
const toggleExpand = (event: Event) => {
|
||||
event.stopPropagation()
|
||||
expanded.value[key] = !expanded.value[key]
|
||||
isExpandedMarketing.value = !isExpandedMarketing.value
|
||||
}
|
||||
|
||||
// 에러 코드 매핑
|
||||
const ERROR_MESSAGES: Record<number, string> = {
|
||||
'-90002': t('Preregist_Alert_Date'),
|
||||
'-90018': t('Preregist_Alert_Birth'),
|
||||
'-90022': t('Preregist_Alert_Age'),
|
||||
'-90000': t('Preregist_Alert_Agree'),
|
||||
'-90023': t('Preregist_Alert_Already'),
|
||||
}
|
||||
|
||||
const showErrorModal = (code: number) => {
|
||||
/**
|
||||
* 에러 모달 표시
|
||||
*/
|
||||
const showErrorModal = (code: number): void => {
|
||||
if (!code) return
|
||||
|
||||
const message = ERROR_MESSAGES[code]
|
||||
|
||||
// 일반 에러 메시지
|
||||
const message = errorMessages.value[code]
|
||||
if (message) {
|
||||
modalStore.handleOpenAlert({ contentText: message })
|
||||
return
|
||||
}
|
||||
|
||||
// 로그인 필요
|
||||
if (code === PREREGIST_ERROR_CODE.LOGIN_REQUIRED) {
|
||||
modalStore.handleOpenConfirm({
|
||||
contentText: tm('Alert_StoveLogin'),
|
||||
confirmButtonText: tm('Text_StoveLogin'),
|
||||
confirmButtonEvent: () => {
|
||||
csrGoStoveLogin()
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 기타 오류
|
||||
modalStore.handleOpenConfirm({
|
||||
contentText: t('Alert_Error'),
|
||||
confirmButtonText: t('Text_Customer'),
|
||||
contentText: tm('Alert_Error'),
|
||||
confirmButtonText: tm('Text_Customer'),
|
||||
confirmButtonEvent: () => {
|
||||
window.open(customerServiceUrl, '_blank')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 토큰 및 사전등록 여부 검증
|
||||
const checkValidation = async () => {
|
||||
if (!props.preregistCode) return false
|
||||
/**
|
||||
* 토큰 및 사전등록 여부 검증
|
||||
*/
|
||||
const checkValidation = async (): Promise<boolean> => {
|
||||
if (!props.preregistCode) {
|
||||
if (import.meta.dev) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[Preregist] preregistCode is required')
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
// 토큰 검증
|
||||
const accessToken = csrGetAccessToken()
|
||||
const isValidToken = await handleTokenValidation(accessToken)
|
||||
if (!isValidToken) return false
|
||||
@@ -154,14 +130,14 @@ const checkValidation = async () => {
|
||||
terms_type: 3,
|
||||
})
|
||||
|
||||
if (result.code === -1) {
|
||||
// 사전등록 가능
|
||||
// 사전등록 가능
|
||||
if (result.code === PREREGIST_ERROR_CODE.NO_DATA) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (result.code === 0) {
|
||||
// 이미 사전등록 완료
|
||||
showErrorModal(-90023)
|
||||
// 이미 사전등록 완료
|
||||
if (result.code === PREREGIST_ERROR_CODE.SUCCESS) {
|
||||
showErrorModal(PREREGIST_ERROR_CODE.ALREADY_REGISTERED)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -171,61 +147,75 @@ const checkValidation = async () => {
|
||||
} catch (error) {
|
||||
if (import.meta.dev) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[checkValidation]', error)
|
||||
console.error('[Preregist.checkValidation]', error)
|
||||
}
|
||||
showErrorModal(-99999)
|
||||
showErrorModal(PREREGIST_ERROR_CODE.UNKNOWN)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 사전등록 모달 오픈
|
||||
const handlePreregist = async () => {
|
||||
/**
|
||||
* 사전등록 모달 오픈
|
||||
*/
|
||||
const handleOpenPreregist = async (): Promise<void> => {
|
||||
if (isSubmitting.value) return
|
||||
|
||||
const isValid = await checkValidation()
|
||||
if (isValid) {
|
||||
isOpen.value = true
|
||||
step.value = 1
|
||||
}
|
||||
}
|
||||
|
||||
// 사전등록 제출
|
||||
const handleSubmit = async () => {
|
||||
if (!props.preregistCode) return
|
||||
if (isSubmitting.value || step.value !== 1) return
|
||||
|
||||
// 유효성 검사
|
||||
if (!canSubmit.value) {
|
||||
showErrorModal(-90000)
|
||||
return
|
||||
}
|
||||
|
||||
const isValid = await checkValidation()
|
||||
if (!isValid) return
|
||||
|
||||
// 국가 정보 조회
|
||||
if (!countryCode.value) {
|
||||
await checkCountryByIp({
|
||||
policy_grp: 'onstove',
|
||||
device_nation: csrGetCountry().toUpperCase(),
|
||||
client_lang: locale.value,
|
||||
include_coverages: false,
|
||||
qc: csrGetQc(),
|
||||
runType: runtimeConfig.public.runType,
|
||||
})
|
||||
}
|
||||
|
||||
isValidated.value = true // 검증 완료 플래그
|
||||
isModalOpen.value = true
|
||||
currentStep.value = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* 사전등록 제출
|
||||
*/
|
||||
const handleSubmit = async (): Promise<void> => {
|
||||
if (!props.preregistCode) return
|
||||
if (isSubmitting.value || currentStep.value !== 1) return
|
||||
|
||||
// 유효성 검사
|
||||
if (!canSubmit.value) {
|
||||
showErrorModal(PREREGIST_ERROR_CODE.REQUIRED_TERMS)
|
||||
return
|
||||
}
|
||||
|
||||
// 이미 검증을 통과한 경우 재검증 스킵
|
||||
if (!isValidated.value) {
|
||||
const isValid = await checkValidation()
|
||||
if (!isValid) return
|
||||
}
|
||||
|
||||
isSubmitting.value = true
|
||||
try {
|
||||
// 생년월일 포맷팅
|
||||
const birthDate = isNorthAmerica.value
|
||||
? `${birthdate.value.year}-${birthdate.value.month.padStart(2, '0')}-${birthdate.value.day.padStart(2, '0')}`
|
||||
: undefined
|
||||
|
||||
// API 호출
|
||||
const result = await setPreregist({
|
||||
accessToken: csrGetAccessToken(),
|
||||
event_code: props.preregistCode,
|
||||
lang_code: locale.value,
|
||||
terms_type: 3,
|
||||
device_type: 'WEB',
|
||||
device_type: device.isMobile ? 'mobile' : 'pc',
|
||||
country_code: countryCode.value || 'KR',
|
||||
necessary_consent1: checks.value.age || isNorthAmerica.value ? 'Y' : 'N',
|
||||
necessary_consent2: checks.value.privacy ? 'Y' : 'N',
|
||||
necessary_consent3: checks.value.marketing ? 'Y' : 'N',
|
||||
birth_date: birthDate,
|
||||
necessary_consent1: 'Y',
|
||||
necessary_consent2: 'Y',
|
||||
necessary_consent3: isCheckedMarketing.value ? 'Y' : 'N',
|
||||
birth_date: '',
|
||||
})
|
||||
|
||||
if (result.code === 0) {
|
||||
step.value = 2
|
||||
if (result.code === PREREGIST_ERROR_CODE.SUCCESS) {
|
||||
currentStep.value = 2
|
||||
return
|
||||
}
|
||||
|
||||
@@ -233,60 +223,46 @@ const handleSubmit = async () => {
|
||||
} catch (error) {
|
||||
if (import.meta.dev) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[handleSubmit]', error)
|
||||
console.error('[Preregist.handleSubmit]', error)
|
||||
}
|
||||
showErrorModal(-99999)
|
||||
showErrorModal(PREREGIST_ERROR_CODE.UNKNOWN)
|
||||
} finally {
|
||||
isSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 모달 닫기 및 초기화
|
||||
const resetForm = () => {
|
||||
checks.value = {
|
||||
age: false,
|
||||
privacy: false,
|
||||
marketing: false,
|
||||
}
|
||||
birthdate.value = {
|
||||
month: '',
|
||||
day: '',
|
||||
year: '',
|
||||
}
|
||||
expanded.value = {
|
||||
privacy: false,
|
||||
marketing: false,
|
||||
}
|
||||
isSubmitting.value = false
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
/**
|
||||
* 모달 닫기 및 상태 초기화
|
||||
*/
|
||||
const handleCloseModal = (): void => {
|
||||
if (isSubmitting.value) return
|
||||
|
||||
step.value = 1
|
||||
// 애니메이션 완료 후 초기화
|
||||
setTimeout(resetForm, 300)
|
||||
currentStep.value = 1
|
||||
isCheckedMarketing.value = false
|
||||
isExpandedMarketing.value = false
|
||||
isSubmitting.value = false
|
||||
isValidated.value = false // 검증 플래그도 초기화
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handlePreregist,
|
||||
handleOpenPreregist,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BlocksModalLayer
|
||||
v-model:is-open="isOpen"
|
||||
v-model:is-open="isModalOpen"
|
||||
area-class="h-full bg-[#292929] pt-[60px] md:w-[476px] md:h-[680px] md:pt-[64px] md:rounded-[20px] md:shadow-[0_2px_4px_rgba(0,0,0,0.06)]"
|
||||
close-class="absolute top-[19px] right-[26px] md:top-[20px] md:right-[24px]"
|
||||
@close="handleClose"
|
||||
@close="handleCloseModal"
|
||||
>
|
||||
<!-- Step 1: Terms Agreement -->
|
||||
<div v-if="step === 1" class="flex flex-col h-full">
|
||||
<div v-if="currentStep === 1" class="flex flex-col h-full">
|
||||
<div class="flex gap-5 px-5 pt-5 pb-[12px] md:px-10 md:pt-6 md:pb-[16px]">
|
||||
<h4
|
||||
class="flex-1 text-xl font-bold leading-[30px] tracking-[-0.6px] text-[#ebebeb] md:text-2xl md:leading-[34px] md:tracking-[-0.72px]"
|
||||
>
|
||||
{{ t('Preregist_Modal_Title01') }}
|
||||
{{ tm('Preregist_Modal_Title01') }}
|
||||
</h4>
|
||||
<div
|
||||
class="flex h-[30px] items-center gap-1 text-base leading-6 tracking-[-0.48px] md:h-[34px]"
|
||||
@@ -305,177 +281,38 @@ defineExpose({
|
||||
<div
|
||||
class="overflow-y-auto h-full py-[24px] px-5 md:py-[32px] md:px-10"
|
||||
>
|
||||
<div
|
||||
class="flex h-12 cursor-pointer items-center rounded-lg border border-white/10 bg-[#383838] px-4 md:px-6 gap-2 md:gap-3"
|
||||
@click="handleCheckAll"
|
||||
>
|
||||
<div class="shrink-0">
|
||||
<AtomsIconsCheckBoldLine
|
||||
:color="allChecked ? 'var(--primary)' : '#666666'"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="flex-1 text-base font-bold leading-6 tracking-[-0.48px] text-[#ebebeb] md:text-lg md:leading-[26px] md:tracking-[-0.54px]"
|
||||
>
|
||||
{{ t('Preregist_Agree_All') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<!-- Age Check (북미 제외) -->
|
||||
<div v-if="!isNorthAmerica" class="px-3 py-4 md:px-6">
|
||||
<div
|
||||
class="flex cursor-pointer items-center gap-3 md:gap-4"
|
||||
@click="handleCheck('age')"
|
||||
<div class="px-3 py-4 md:px-6">
|
||||
<div class="flex cursor-pointer items-center gap-3 md:gap-4">
|
||||
<div class="shrink-0">
|
||||
<AtomsIconsCheckBoldLine
|
||||
:color="isCheckedMarketing ? 'var(--primary)' : '#666666'"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
|
||||
@click="toggleMarketing"
|
||||
>
|
||||
<div class="shrink-0">
|
||||
<AtomsIconsCheckBoldLine
|
||||
:color="checks.age ? 'var(--primary)' : '#666666'"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
|
||||
>
|
||||
{{ t('Preregist_Agree_Age') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Privacy Check with Accordion -->
|
||||
<div class="px-3 py-4 md:px-6">
|
||||
<div class="flex cursor-pointer items-center gap-3 md:gap-4">
|
||||
<div class="shrink-0">
|
||||
<AtomsIconsCheckBoldLine
|
||||
:color="checks.privacy ? 'var(--primary)' : '#666666'"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
|
||||
@click="handleCheck('privacy')"
|
||||
>
|
||||
{{ t('Preregist_Agree_Privacy') }}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center justify-center transition-transform duration-200"
|
||||
:class="{ 'rotate-180': expanded.privacy }"
|
||||
@click="toggleExpand('privacy', $event)"
|
||||
>
|
||||
<AtomsIconsArrowDownLine />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Privacy Detail Content -->
|
||||
<div
|
||||
v-if="expanded.privacy"
|
||||
class="mt-4 max-h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
|
||||
{{ tmWithGameName('Preregist_Agree_News') }}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center justify-center transition-transform duration-200"
|
||||
:class="{ 'rotate-180': isExpandedMarketing }"
|
||||
@click="toggleExpand($event)"
|
||||
>
|
||||
<p
|
||||
v-dompurify-html="t('Preregist_Agree_Privacy_Info')"
|
||||
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#b2b2b2]"
|
||||
></p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Marketing Check with Accordion -->
|
||||
<div class="px-3 py-4 md:px-6">
|
||||
<div class="flex cursor-pointer items-center gap-3 md:gap-4">
|
||||
<div class="shrink-0">
|
||||
<AtomsIconsCheckBoldLine
|
||||
:color="checks.marketing ? 'var(--primary)' : '#666666'"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="flex-1 text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
|
||||
@click="handleCheck('marketing')"
|
||||
>
|
||||
{{ t('Preregist_Agree_News') }}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center justify-center transition-transform duration-200"
|
||||
:class="{ 'rotate-180': expanded.marketing }"
|
||||
@click="toggleExpand('marketing', $event)"
|
||||
>
|
||||
<AtomsIconsArrowDownLine />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Marketing Detail Content -->
|
||||
<div
|
||||
v-if="expanded.marketing"
|
||||
class="mt-4 max-h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
|
||||
>
|
||||
<p
|
||||
v-dompurify-html="tWithGameName('Preregist_Agree_News_Info')"
|
||||
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#b2b2b2]"
|
||||
></p>
|
||||
</div>
|
||||
<AtomsIconsArrowDownLine />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Birthdate Input (북미 등) -->
|
||||
<!-- Marketing Detail Content -->
|
||||
<div
|
||||
v-if="isNorthAmerica"
|
||||
class="flex flex-col gap-6 pb-4 pl-[44px] pr-3 pt-2 md:pl-[60px] md:pr-6"
|
||||
v-if="isExpandedMarketing"
|
||||
class="mt-4 max-h-[160px] overflow-y-auto rounded-lg bg-white/[0.04] px-4 py-3"
|
||||
>
|
||||
<!-- Divider -->
|
||||
<div class="h-px w-full bg-white/[0.06]"></div>
|
||||
|
||||
<!-- Birthdate Form -->
|
||||
<div class="flex flex-col gap-3 md:gap-4">
|
||||
<p
|
||||
class="text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-[15px] md:tracking-[-0.45px]"
|
||||
>
|
||||
{{ t('Preregist_Agree_Birth') }}
|
||||
</p>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<!-- Month -->
|
||||
<label class="flex-1">
|
||||
<span class="sr-only">Month</span>
|
||||
<input
|
||||
id="birthdate-month"
|
||||
v-model="birthdate.month"
|
||||
type="number"
|
||||
name="birthdate-month"
|
||||
placeholder="Month"
|
||||
min="1"
|
||||
max="12"
|
||||
aria-label="Birth month"
|
||||
class="h-12 w-full rounded-lg border border-[#595959] bg-[#292929] px-4 py-3 text-sm font-normal leading-5 tracking-[-0.42px] text-[#ebebeb] placeholder:text-[#666666] focus:border-[#7f7f7f] focus:outline-none"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<!-- Day -->
|
||||
<label class="flex-1">
|
||||
<span class="sr-only">Day</span>
|
||||
<input
|
||||
id="birthdate-day"
|
||||
v-model="birthdate.day"
|
||||
type="number"
|
||||
name="birthdate-day"
|
||||
placeholder="Day"
|
||||
min="1"
|
||||
max="31"
|
||||
aria-label="Birth day"
|
||||
class="h-12 w-full rounded-lg border border-[#595959] bg-[#292929] px-4 py-3 text-sm font-normal leading-5 tracking-[-0.42px] text-[#ebebeb] placeholder:text-[#666666] focus:border-[#7f7f7f] focus:outline-none"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<!-- Year -->
|
||||
<label class="flex-1">
|
||||
<span class="sr-only">Year</span>
|
||||
<input
|
||||
id="birthdate-year"
|
||||
v-model="birthdate.year"
|
||||
type="number"
|
||||
name="birthdate-year"
|
||||
placeholder="Year"
|
||||
min="1900"
|
||||
:max="currentYear"
|
||||
aria-label="Birth year"
|
||||
class="h-12 w-full rounded-lg border border-[#595959] bg-[#292929] px-4 py-3 text-sm font-normal leading-5 tracking-[-0.42px] text-[#ebebeb] placeholder:text-[#666666] focus:border-[#7f7f7f] focus:outline-none"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
v-dompurify-html="tmWithGameName('Preregist_Agree_News_Info')"
|
||||
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#b2b2b2]"
|
||||
></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -491,18 +328,18 @@ defineExpose({
|
||||
:disabled="!canSubmit || isSubmitting"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
{{ t('Preregist_Btn_Preegist') }}
|
||||
{{ tm('Preregist_Btn_Preegist') }}
|
||||
</AtomsButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 2: Success -->
|
||||
<div v-if="step === 2" class="flex flex-1 flex-col h-full">
|
||||
<div v-if="currentStep === 2" class="flex flex-1 flex-col h-full">
|
||||
<div class="flex gap-5 px-5 pb-10 pt-5 md:px-10 md:pb-12 md:pt-6">
|
||||
<h4
|
||||
class="flex-1 text-xl font-bold leading-[30px] tracking-[-0.6px] text-[#ebebeb] md:text-2xl md:leading-[34px] md:tracking-[-0.72px]"
|
||||
>
|
||||
{{ t('Preregist_Modal_Title02') }}
|
||||
{{ tm('Preregist_Modal_Title02') }}
|
||||
</h4>
|
||||
<div
|
||||
class="flex h-[30px] items-center gap-1 text-base leading-6 tracking-[-0.48px] md:h-[34px]"
|
||||
@@ -521,7 +358,7 @@ defineExpose({
|
||||
<p
|
||||
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#b2b2b2] opacity-50 md:text-[15px] md:leading-6 md:tracking-[-0.45px]"
|
||||
>
|
||||
{{ currentDate }}
|
||||
{{ preregistDate }}
|
||||
</p>
|
||||
<h3
|
||||
class="text-xl font-bold leading-[30px] tracking-[-0.6px] text-[#ebebeb] md:text-2xl md:leading-[34px] md:tracking-[-0.72px]"
|
||||
@@ -531,7 +368,7 @@ defineExpose({
|
||||
<p
|
||||
class="text-[13px] font-normal leading-[22px] tracking-[-0.325px] text-[#ebebeb] md:text-[15px] md:leading-6 md:tracking-[-0.45px]"
|
||||
>
|
||||
{{ t('Preregist_Agree_News_Complete') }}
|
||||
{{ tm('Preregist_Agree_News_Complete') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -540,7 +377,7 @@ defineExpose({
|
||||
<p
|
||||
class="text-left text-sm font-medium leading-6 tracking-[-0.42px] text-[#ebebeb] md:text-center md:text-base md:leading-[26px] md:tracking-[-0.48px]"
|
||||
>
|
||||
{{ t('Preregist_Stove_Download') }}
|
||||
{{ tm('Preregist_Stove_Download') }}
|
||||
</p>
|
||||
<div class="flex items-center gap-3">
|
||||
<div
|
||||
@@ -611,16 +448,4 @@ defineExpose({
|
||||
:deep(.overflow-y-auto::-webkit-scrollbar-thumb:hover) {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
/* Remove number input spinner */
|
||||
input[type='number']::-webkit-inner-spin-button,
|
||||
input[type='number']::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user