130 lines
4.4 KiB
Vue
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>
|