릴리스: v1.3.29 가이드 진입점과 인증 초기화 안정화
This commit is contained in:
@@ -30,8 +30,15 @@ const description = computed(() =>
|
||||
: '저장한 티어표와 즐겨찾기, 프로필 설정을 이어서 관리할 수 있어요.'
|
||||
)
|
||||
const submitLabel = computed(() => (mode.value === 'signup' ? '가입하기' : '로그인'))
|
||||
const authReady = computed(() => auth.hydrated)
|
||||
const checkingSession = computed(() => !authReady.value || auth.status === 'loading')
|
||||
|
||||
onMounted(async () => {
|
||||
if (!auth.hydrated) await auth.refresh()
|
||||
if (auth.user) {
|
||||
router.replace(typeof route.query.redirect === 'string' ? route.query.redirect : '/me')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const meta = await api.authMeta()
|
||||
hasUsers.value = !!meta.hasUsers
|
||||
@@ -40,6 +47,15 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => [auth.hydrated, auth.user],
|
||||
([hydrated, user]) => {
|
||||
if (!hydrated || !user) return
|
||||
router.replace(typeof route.query.redirect === 'string' ? route.query.redirect : '/me')
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
async function submit() {
|
||||
error.value = ''
|
||||
if (mode.value === 'signup' && password.value !== passwordConfirm.value) {
|
||||
@@ -66,7 +82,11 @@ async function submit() {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="authScreen">
|
||||
<section v-if="checkingSession" class="authScreen authScreen--loading">
|
||||
<div class="authLoading">로그인 상태를 확인하고 있어요.</div>
|
||||
</section>
|
||||
|
||||
<section v-else class="authScreen">
|
||||
<div class="authTabs" role="tablist" aria-label="로그인 또는 회원가입">
|
||||
<button type="button" class="authTabs__button" :class="{ 'authTabs__button--active': mode === 'login' }" @click="mode = 'login'">
|
||||
로그인
|
||||
@@ -128,6 +148,16 @@ async function submit() {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.authScreen--loading {
|
||||
min-height: 220px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.authLoading {
|
||||
color: rgba(255, 255, 255, 0.62);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.authTabs {
|
||||
display: inline-flex;
|
||||
gap: 8px;
|
||||
|
||||
@@ -30,14 +30,19 @@ const avatarUrl = computed(() => {
|
||||
return toApiUrl(auth.user.avatarSrc)
|
||||
})
|
||||
|
||||
const authReady = computed(() => auth.hydrated)
|
||||
|
||||
const displayInitial = computed(() => {
|
||||
const email = auth.user?.email || 'U'
|
||||
return email[0].toUpperCase()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await auth.refresh()
|
||||
if (!auth.user) router.push('/login')
|
||||
if (!auth.hydrated) await auth.refresh()
|
||||
if (!auth.user) {
|
||||
router.replace('/login')
|
||||
return
|
||||
}
|
||||
nickname.value = auth.user?.nickname || ''
|
||||
removeAvatar.value = false
|
||||
})
|
||||
@@ -121,7 +126,11 @@ async function logout() {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section v-if="auth.user" class="settingsScreen">
|
||||
<section v-if="!authReady" class="settingsScreen settingsScreen--loading">
|
||||
<div class="settingsLoading">계정 정보를 불러오고 있어요.</div>
|
||||
</section>
|
||||
|
||||
<section v-else-if="auth.user" class="settingsScreen">
|
||||
<div class="settingsIdentity">
|
||||
<div class="avatarButtonWrap">
|
||||
<button class="avatarButton" type="button" @click="openAvatarPicker">
|
||||
@@ -185,6 +194,16 @@ async function logout() {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.settingsScreen--loading {
|
||||
min-height: 240px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.settingsLoading {
|
||||
color: rgba(255, 255, 255, 0.62);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.settingsIdentity {
|
||||
display: grid;
|
||||
grid-template-columns: 120px minmax(0, 1fr);
|
||||
|
||||
Reference in New Issue
Block a user