100 lines
2.3 KiB
Vue
100 lines
2.3 KiB
Vue
<script setup>
|
|
import {useErrorStore} from '@/stores/errors'
|
|
import {useAuthStore} from '@/stores/auth'
|
|
import router from '@/router'
|
|
import {ref} from 'vue'
|
|
import Loader from '@/components/Loader.vue'
|
|
|
|
const apiHost = import.meta.env.VITE_CONJUREOS_HOST
|
|
|
|
const errorStore = useErrorStore()
|
|
const isLoginIn = ref(false)
|
|
const login = (form) => {
|
|
const formData = new FormData(form)
|
|
isLoginIn.value = true
|
|
fetch(apiHost + 'login', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then((response) => {
|
|
isLoginIn.value = false
|
|
if (response.status !== 200)
|
|
return response.text().then(error => {
|
|
throw new Error(error)
|
|
}
|
|
)
|
|
return response.text()
|
|
})
|
|
.then((result) => {
|
|
useAuthStore().set(JSON.parse(result))
|
|
router.push('/')
|
|
})
|
|
.catch((error) => {
|
|
isLoginIn.value = false
|
|
errorStore.unshift(error)
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<article>
|
|
<h1>Login</h1>
|
|
<form ref="loginForm" enctype="multipart/form-data" @submit.prevent="login($refs.loginForm)">
|
|
<label for="username">username</label>
|
|
<input
|
|
required
|
|
type="text"
|
|
class="border border-primary rounded-lg px-3 py-2 bg-transparent focus:outline-none focus:border-accent"
|
|
name="username"
|
|
id="username"
|
|
/>
|
|
<label for="password">password</label>
|
|
<input
|
|
required
|
|
type="password"
|
|
class="border border-primary rounded-lg px-3 py-2 bg-transparent focus:outline-none focus:border-accent"
|
|
name="password"
|
|
id="password"
|
|
/>
|
|
<button
|
|
v-if="!isLoginIn"
|
|
class="bg-transparent text-primary font-semibold hover:text-white py-2 px-4 border border-gray-500 hover:border-transparent rounded"
|
|
type="submit"
|
|
>
|
|
Login
|
|
</button>
|
|
<span class="loader" v-else>
|
|
<Loader :variant="2"/>
|
|
</span>
|
|
</form>
|
|
</article>
|
|
</template>
|
|
|
|
<style scoped>
|
|
form {
|
|
padding: 1rem 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2rem;
|
|
position: relative;
|
|
}
|
|
|
|
.loader {
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 50%;
|
|
height: 6rem;
|
|
transform: translateX(-50%);
|
|
}
|
|
|
|
input {
|
|
outline: none !important;
|
|
outline-offset: 0 !important;
|
|
--tw-ring-color: --vt-c-silver !important;
|
|
}
|
|
|
|
label {
|
|
margin-bottom: -1.5rem;
|
|
}
|
|
</style>
|