Files
planner.sori.studio/src/components/AuthDialog.vue
2026-04-21 18:06:24 +09:00

130 lines
4.4 KiB
Vue

<script setup>
const props = defineProps({
open: {
type: Boolean,
default: false,
},
mode: {
type: String,
default: 'login',
},
form: {
type: Object,
required: true,
},
busy: {
type: Boolean,
default: false,
},
message: {
type: String,
default: '',
},
})
const emit = defineEmits([
'close',
'submit',
'switch-mode',
'update:field',
])
function updateField(field, event) {
emit('update:field', {
field,
value: event.target.value,
})
}
</script>
<template>
<div
v-if="open"
class="fixed inset-0 z-50 flex items-center justify-center bg-stone-900/45 px-4 py-8 backdrop-blur-sm"
>
<div class="w-full max-w-md rounded-[28px] border border-white/60 bg-[#f6f1e8] p-6 shadow-2xl sm:p-7">
<div class="flex items-start justify-between gap-4">
<div class="space-y-2">
<p class="text-[11px] font-bold uppercase tracking-[0.24em] text-stone-500">Account</p>
<h2 class="text-2xl font-semibold tracking-[-0.04em] text-stone-900">
{{ mode === 'login' ? '로그인' : '회원가입' }}
</h2>
<p class="text-sm leading-6 text-stone-600">
{{ mode === 'login' ? '저장된 플래너를 다시 이어서 볼 수 있습니다.' : '사용자별 기록과 통계를 연결하기 위한 계정을 만듭니다.' }}
</p>
</div>
<button
type="button"
class="rounded-full border border-stone-300 px-3 py-2 text-[10px] font-bold tracking-[0.16em] text-stone-500 transition hover:border-stone-500 hover:text-stone-900"
@click="emit('close')"
>
CLOSE
</button>
</div>
<form class="mt-6 space-y-4" @submit.prevent="emit('submit')">
<div v-if="mode === 'signup'" class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">닉네임</label>
<input
:value="form.nickname"
type="text"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
placeholder="닉네임을 입력해 주세요."
@input="updateField('nickname', $event)"
/>
</div>
<div class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">이메일</label>
<input
:value="form.email"
type="email"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
placeholder="zenn@example.com"
@input="updateField('email', $event)"
/>
</div>
<div class="space-y-2">
<label class="text-[11px] font-bold tracking-[0.16em] text-stone-600">비밀번호</label>
<input
:value="form.password"
type="password"
class="w-full rounded-2xl border border-stone-300 bg-white px-4 py-3 text-sm font-semibold text-stone-800 outline-none transition focus:border-stone-500"
placeholder="8자 이상 입력해 주세요."
@input="updateField('password', $event)"
/>
</div>
<p
v-if="message"
class="rounded-2xl border border-stone-300 bg-white/80 px-4 py-3 text-sm font-semibold leading-6 text-stone-700"
>
{{ message }}
</p>
<button
type="submit"
class="w-full rounded-full bg-stone-900 px-5 py-3 text-xs font-bold tracking-[0.18em] text-white transition hover:bg-stone-700 disabled:cursor-not-allowed disabled:bg-stone-400"
:disabled="busy"
>
{{ busy ? '처리 중...' : mode === 'login' ? 'LOGIN' : 'SIGN UP' }}
</button>
</form>
<div class="mt-5 flex items-center justify-between gap-3 rounded-2xl border border-stone-300 bg-white/70 px-4 py-3">
<p class="text-sm font-semibold text-stone-600">
{{ mode === 'login' ? '아직 계정이 없나요?' : '이미 계정이 있나요?' }}
</p>
<button
type="button"
class="text-xs font-bold tracking-[0.16em] text-stone-900 underline underline-offset-4"
@click="emit('switch-mode', mode === 'login' ? 'signup' : 'login')"
>
{{ mode === 'login' ? '회원가입' : '로그인' }}
</button>
</div>
</div>
</div>
</template>