diff --git a/app/pages/login.vue b/app/pages/login.vue index cb9d3f8..2ca4a93 100644 --- a/app/pages/login.vue +++ b/app/pages/login.vue @@ -2,40 +2,110 @@ definePageMeta({ layout: false }); const supabase = useSupabaseClient(); -const email = ref(""); + +type ViewMode = 'auth' | 'forgot-password'; + +const email = ref(''); +const password = ref(''); +const passwordConfirm = ref(''); const loading = ref(false); -const message = ref(""); -const error = ref(""); +const message = ref(''); +const error = ref(''); +const activeTab = ref<'login' | 'signup'>('login'); +const viewMode = ref('auth'); -async function sendMagicLink() { - if (!email.value) return; +function resetForm() { + email.value = ''; + password.value = ''; + passwordConfirm.value = ''; + error.value = ''; + message.value = ''; +} + +function translateAuthError(msg: string): string { + if (msg.includes('Invalid login credentials')) return '이메일 또는 비밀번호가 올바르지 않습니다.'; + if (msg.includes('Email not confirmed')) return '이메일 확인이 완료되지 않았습니다. 받은 편지함을 확인해주세요.'; + if (msg.includes('User already registered')) return '이미 가입된 이메일입니다. 로그인을 시도해주세요.'; + if (msg.includes('Password should be at least 6 characters')) return '비밀번호는 최소 6자 이상이어야 합니다.'; + return msg; +} + +async function signIn() { + if (!email.value || !password.value) return; loading.value = true; - error.value = ""; - message.value = ""; + error.value = ''; + message.value = ''; - const { error: err } = await supabase.auth.signInWithOtp({ + const { error: err } = await supabase.auth.signInWithPassword({ email: email.value, - options: { - emailRedirectTo: `${window.location.origin}/confirm`, - }, + password: password.value, }); loading.value = false; if (err) { - error.value = err.message; + error.value = translateAuthError(err.message); } else { - message.value = `${email.value}로 로그인 링크를 전송했습니다. 이메일을 확인해주세요.`; + await navigateTo('/'); + } +} + +async function signUp() { + if (!email.value || !password.value) return; + if (password.value !== passwordConfirm.value) { + error.value = '비밀번호가 일치하지 않습니다.'; + return; + } + + loading.value = true; + error.value = ''; + message.value = ''; + + const { data, error: err } = await supabase.auth.signUp({ + email: email.value, + password: password.value, + }); + + loading.value = false; + if (err) { + error.value = translateAuthError(err.message); + } else if (data.session) { + await navigateTo('/'); + } else { + message.value = `${email.value}로 확인 이메일을 전송했습니다. 이메일을 확인한 후 로그인해주세요.`; + } +} + +async function sendResetEmail() { + if (!email.value) return; + loading.value = true; + error.value = ''; + message.value = ''; + + const { error: err } = await supabase.auth.resetPasswordForEmail(email.value, { + redirectTo: `${window.location.origin}/confirm`, + }); + + loading.value = false; + if (err) { + error.value = translateAuthError(err.message); + } else { + message.value = `${email.value}로 비밀번호 재설정 링크를 전송했습니다.`; } } async function signInWithGoogle() { await supabase.auth.signInWithOAuth({ - provider: "google", + provider: 'google', options: { redirectTo: `${window.location.origin}/confirm`, }, }); } + +const tabs = [ + { label: '로그인', value: 'login' }, + { label: '회원가입', value: 'signup' }, +];