90 lines
2.6 KiB
Vue
90 lines
2.6 KiB
Vue
<template>
|
|
<div
|
|
class="flex min-h-full items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8"
|
|
>
|
|
<div class="w-full max-w-md space-y-8">
|
|
<div>
|
|
<h2
|
|
class="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900"
|
|
>
|
|
Sign in to your account
|
|
</h2>
|
|
</div>
|
|
<Transition
|
|
enter-active-class="transition-height ease-out duration-500 origin-bottom overflow-hidden"
|
|
enter-from-class="h-0"
|
|
enter-to-class="h-10"
|
|
>
|
|
<div class="mb-4 rounded" v-if="errorMessage">
|
|
<div
|
|
class="rounded bg-red-100 px-4 py-2 text-center font-bold text-red-700"
|
|
role="alert"
|
|
aria-live="assertive"
|
|
>
|
|
{{ errorMessage }}
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
<Form
|
|
@submit="doLogin"
|
|
class="mt-8 overflow-hidden shadow sm:rounded-md"
|
|
:validators="validators"
|
|
>
|
|
<div>
|
|
<div class="bg-white px-4 py-5 sm:p-6">
|
|
<div class="space-y-5">
|
|
<FormField name="email" label="Email address" type="email" />
|
|
<FormField name="password" label="Password" type="password" />
|
|
</div>
|
|
</div>
|
|
<div class="bg-gray-50 px-4 py-3 text-right sm:px-6">
|
|
<Button button-type="submit">Sign in</Button>
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import Button from '../components/Button.vue';
|
|
import { FormSubmit } from '../components/form/form.types';
|
|
import Form from '../components/form/Form.vue';
|
|
import FormField from '../components/form/FormField.vue';
|
|
import { IsEmail, IsRequired } from '../components/form/validators';
|
|
import { useUserStore } from '../store/user.store';
|
|
import { JFetchError } from '../utils/jfetch';
|
|
|
|
const userStore = useUserStore();
|
|
const router = useRouter();
|
|
const errorMessage = ref<string>('');
|
|
const validators = [
|
|
{
|
|
field: 'email',
|
|
validators: [IsRequired(), IsEmail()],
|
|
},
|
|
{
|
|
field: 'password',
|
|
validators: [IsRequired()],
|
|
},
|
|
];
|
|
|
|
const doLogin = async (submit: FormSubmit) => {
|
|
errorMessage.value = '';
|
|
if (!submit.isValid) return;
|
|
try {
|
|
const { email, password } = submit.formData;
|
|
await userStore.login({
|
|
email: email as string,
|
|
password: password as string,
|
|
});
|
|
router.replace({ name: 'dashboard' });
|
|
} catch (e) {
|
|
const error = e as JFetchError;
|
|
errorMessage.value = error?.data?.message || (e as Error).message;
|
|
}
|
|
};
|
|
</script>
|