Files
sori.studio/pages/admin/login.vue

102 lines
3.1 KiB
Vue

<script setup>
definePageMeta({
layout: false
})
const form = reactive({
email: '',
password: ''
})
const pending = ref(false)
const errorMessage = ref('')
/**
* 로그인 제출 가능 여부(이메일·비밀번호가 모두 채워졌는지)
* @returns {boolean} 제출 가능 여부
*/
const canSubmitAdminLogin = computed(() => Boolean(form.email.trim()) && Boolean(form.password))
const { data: bootstrapStatus } = await useFetch('/api/auth/bootstrap-status', {
default: () => ({
hasUsers: true,
needsAdminSetup: false
})
})
/**
* 관리자 로그인 제출
* @returns {Promise<void>} 로그인 처리 결과
*/
const submitLogin = async () => {
pending.value = true
errorMessage.value = ''
try {
await $fetch('/admin/api/auth/login', {
method: 'POST',
body: form
})
await navigateTo('/admin')
} catch {
errorMessage.value = '이메일 또는 비밀번호를 확인해 주세요.'
} finally {
pending.value = false
}
}
</script>
<template>
<main class="admin-login flex min-h-screen items-center justify-center bg-[#f5f5f2] px-5 text-ink">
<section class="admin-login__panel w-full max-w-sm border border-line bg-paper p-8">
<p class="admin-login__eyebrow text-xs font-semibold uppercase text-muted">
Admin
</p>
<h1 class="admin-login__title mt-2 text-3xl font-semibold">
로그인
</h1>
<p
v-if="bootstrapStatus?.needsAdminSetup"
class="mt-3 rounded border border-[#ff4f2e]/30 bg-[#ff4f2e]/10 px-3 py-2 text-xs text-[#b63a23]"
>
등록된 관리자가 없습니다.
<NuxtLink class="font-semibold underline-offset-2 hover:underline" to="/signup">
관리자 등록으로 이동
</NuxtLink>
</p>
<form class="admin-login__form mt-8 grid gap-4" @submit.prevent="submitLogin">
<label class="admin-login__field grid gap-2 text-sm">
<span class="admin-login__label font-medium">이메일</span>
<input
v-model="form.email"
class="admin-login__input rounded border border-line bg-white px-3 py-2"
type="email"
autocomplete="username"
required
>
</label>
<label class="admin-login__field grid gap-2 text-sm">
<span class="admin-login__label font-medium">비밀번호</span>
<input
v-model="form.password"
class="admin-login__input rounded border border-line bg-white px-3 py-2"
type="password"
autocomplete="current-password"
required
>
</label>
<p v-if="errorMessage" class="admin-login__error text-sm text-red-600">
{{ errorMessage }}
</p>
<button
class="admin-login__button rounded bg-[#15171a] px-4 py-2 text-sm font-semibold text-white disabled:cursor-not-allowed disabled:opacity-50"
type="submit"
:disabled="pending || !canSubmitAdminLogin"
>
{{ pending ? '확인 중' : '로그인' }}
</button>
</form>
</section>
</main>
</template>