Dynavera/site/src/views/LoginView.vue

118 lines
3.9 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { reactive, computed, onMounted, ref } from 'vue'
import type { VNodeRef } from 'vue'
defineOptions({ name: 'LoginView' })
import { useRouter, useRoute } from 'vue-router'
import { Card, Typography, Form, Input, Button, message } from 'ant-design-vue'
import { useUserStore } from '../stores/userStore'
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const loading = computed(() => userStore.loading)
const formRef = ref<VNodeRef | null>(null)
const formState = reactive({
email: '',
password: '',
})
const submit = async () => {
try {
await userStore.login(formState.email, formState.password)
message.success('Login successful')
const redirect = (route.query.redirect as string) || '/organization'
router.push(redirect)
} catch (error: unknown) {
let errorMsg = 'Login failed'
if (userStore.error) {
errorMsg = userStore.error
} else if (typeof error === 'string') {
errorMsg = error
} else if (error instanceof Error) {
errorMsg = error.message || 'Login failed'
} else if (typeof error === 'object' && error !== null) {
const errObj = error as { [k: string]: unknown }
const maybeResp = errObj?.response as unknown
if (typeof maybeResp === 'object' && maybeResp !== null) {
const respObj = maybeResp as { data?: unknown }
const data = respObj.data
if (typeof data === 'object' && data !== null) {
const detail = (data as { detail?: unknown }).detail
const msg = (data as { message?: unknown }).message
if (typeof detail === 'string') {
errorMsg = detail
} else if (typeof msg === 'string') {
errorMsg = msg
}
}
}
}
message.error(errorMsg)
}
}
onMounted(async () => {
await userStore.fetchSession()
if (userStore.isAuthenticated) {
const redirect = (route.query.redirect as string) || '/organization'
router.replace(redirect)
}
})
</script>
<template>
<div class="auth-page">
<Card class="panel" :bordered="false">
<Typography.Title :level="3">Login</Typography.Title>
<Form :ref="formRef" layout="vertical" :model="formState" @finish="submit">
<Form.Item
label="Email"
name="email"
:rules="[
{ required: true, message: 'Enter your email' },
{
type: 'email',
message: 'Please enter a valid email',
},
]"
>
<Input
v-model:value="formState.email"
type="email"
placeholder="Email address"
:disabled="loading"
/>
</Form.Item>
<Form.Item
label="Password"
name="password"
:rules="[{ required: true, message: 'Enter your password' }]"
>
<Input.Password
v-model:value="formState.password"
placeholder="Password"
:disabled="loading"
/>
</Form.Item>
<Button type="primary" html-type="submit" block :loading="loading">Login</Button>
</Form>
</Card>
</div>
</template>
<style scoped>
.auth-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 1rem;
}
.panel {
max-width: 400px;
width: 100%;
}
</style>