wire frontend password login
This commit is contained in:
parent
1dff3f6976
commit
3da9c586c3
4 changed files with 239 additions and 3 deletions
|
|
@ -1,7 +1,60 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { z } from 'zod'
|
||||
|
||||
import AuthForm from '@/components/AuthForm.vue'
|
||||
import AuthLayout from '@/components/AuthLayout.vue'
|
||||
import AuthTextField from '@/components/AuthTextField.vue'
|
||||
import { type LoginFieldErrors, useAuthStore } from '@/stores/auth'
|
||||
|
||||
const emailSchema = z.string().email()
|
||||
const email = ref('')
|
||||
const password = ref('')
|
||||
const fieldErrors = ref<LoginFieldErrors>({})
|
||||
const authStore = useAuthStore()
|
||||
const { loading, error } = storeToRefs(authStore)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
async function submitLogin(): Promise<void> {
|
||||
const normalizedEmail = email.value.trim()
|
||||
fieldErrors.value = validateLogin(normalizedEmail, password.value)
|
||||
if (Object.keys(fieldErrors.value).length > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const result = await authStore.login(normalizedEmail, password.value)
|
||||
if (!result.success) {
|
||||
fieldErrors.value = result.fieldErrors
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
await router.push(safeLoginRedirect(route.query.redirect))
|
||||
}
|
||||
|
||||
function validateLogin(submittedEmail: string, submittedPassword: string): LoginFieldErrors {
|
||||
const errors: LoginFieldErrors = {}
|
||||
|
||||
if (!emailSchema.safeParse(submittedEmail).success) {
|
||||
errors.email = 'Enter a valid email address.'
|
||||
}
|
||||
if (submittedPassword === '') {
|
||||
errors.password = 'Enter your password.'
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
function safeLoginRedirect(redirect: unknown): string {
|
||||
if (typeof redirect === 'string' && redirect.startsWith('/') && !redirect.startsWith('//')) {
|
||||
return redirect
|
||||
}
|
||||
|
||||
return '/dashboard'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -10,13 +63,22 @@ import AuthTextField from '@/components/AuthTextField.vue'
|
|||
title="Welcome back"
|
||||
description="Pick up where you left off and keep your momentum going."
|
||||
>
|
||||
<AuthForm submit-label="Log in">
|
||||
<AuthForm
|
||||
submit-label="Log in"
|
||||
submitting-label="Logging in..."
|
||||
:submitting="loading"
|
||||
:error="error ?? undefined"
|
||||
@submit="submitLogin"
|
||||
>
|
||||
<AuthTextField
|
||||
id="login-email"
|
||||
label="Email address"
|
||||
type="email"
|
||||
autocomplete="email"
|
||||
placeholder="you@example.com"
|
||||
v-model="email"
|
||||
:error="fieldErrors.email"
|
||||
:disabled="loading"
|
||||
/>
|
||||
<AuthTextField
|
||||
id="login-password"
|
||||
|
|
@ -24,6 +86,9 @@ import AuthTextField from '@/components/AuthTextField.vue'
|
|||
type="password"
|
||||
autocomplete="current-password"
|
||||
placeholder="Enter your password"
|
||||
v-model="password"
|
||||
:error="fieldErrors.password"
|
||||
:disabled="loading"
|
||||
/>
|
||||
</AuthForm>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue