130 lines
3 KiB
Vue
130 lines
3 KiB
Vue
|
<script setup lang="ts">
|
||
|
/* global $fetch */
|
||
|
import { ref, watch } from "vue";
|
||
|
import { VForm } from "vuetify/components";
|
||
|
import { navigateTo, useCookie, useFetch, useRoute } from "nuxt/app";
|
||
|
import { cookieSettings } from "~/utils/cookieSettings";
|
||
|
import { definePageMeta } from "~/.nuxt/imports";
|
||
|
|
||
|
const route = useRoute();
|
||
|
|
||
|
const login = ref("");
|
||
|
const password = ref("");
|
||
|
const loading = ref(false);
|
||
|
const error = ref<true | string>(true);
|
||
|
const form = ref<VForm | null>(null);
|
||
|
const loggedIn = ref<boolean>(useCookie("token", cookieSettings).value != null);
|
||
|
|
||
|
const redirectTo = ref(route.redirectedFrom);
|
||
|
|
||
|
definePageMeta({
|
||
|
layout: false,
|
||
|
});
|
||
|
|
||
|
async function submit() {
|
||
|
loading.value = true;
|
||
|
try {
|
||
|
const result = await $fetch("/api/login", {
|
||
|
body: { login: login.value, password: password.value },
|
||
|
method: "POST",
|
||
|
});
|
||
|
console.log(result);
|
||
|
loggedIn.value = true;
|
||
|
password.value = "";
|
||
|
} catch (e) {
|
||
|
console.log(typeof e);
|
||
|
console.error(e);
|
||
|
console.log(e);
|
||
|
error.value = (e as any).data.message;
|
||
|
}
|
||
|
loading.value = false;
|
||
|
if (redirectTo.value) navigateTo(redirectTo.value.fullPath);
|
||
|
if (form.value) form.value.validate();
|
||
|
}
|
||
|
|
||
|
async function logout() {
|
||
|
try {
|
||
|
await $fetch("/api/logout");
|
||
|
loggedIn.value = false;
|
||
|
} catch (e) {
|
||
|
console.error(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const userInfo = ref(JSON.stringify(useFetch("/api/users/me").data));
|
||
|
watch(loggedIn, updateUserInfo);
|
||
|
async function updateUserInfo() {
|
||
|
if (loggedIn.value) {
|
||
|
try {
|
||
|
userInfo.value = JSON.stringify(await $fetch("/api/users/me"));
|
||
|
} catch (e) {
|
||
|
// expected if the user is not logged in
|
||
|
userInfo.value = "";
|
||
|
}
|
||
|
} else {
|
||
|
userInfo.value = "";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
updateUserInfo();
|
||
|
</script>
|
||
|
|
||
|
<template>
|
||
|
<VCard max-width="450px" class="mx-auto mt-16" variant="outlined">
|
||
|
<VProgressLinear
|
||
|
absolute
|
||
|
:active="loading"
|
||
|
:indeterminate="loading"
|
||
|
color="primary"
|
||
|
/>
|
||
|
<template #title>
|
||
|
Log in
|
||
|
</template>
|
||
|
<template #text>
|
||
|
<VForm v-if="!loggedIn" ref="form" class="form" :disabled="loading">
|
||
|
<VTextField
|
||
|
v-model="login"
|
||
|
label="Login"
|
||
|
:rules="[() => error]"
|
||
|
:disabled="loggedIn"
|
||
|
autocomplete="username"
|
||
|
variant="outlined"
|
||
|
color="primary"
|
||
|
/>
|
||
|
<VTextField
|
||
|
v-model="password"
|
||
|
label="Password"
|
||
|
type="password"
|
||
|
:rules="[() => error]"
|
||
|
:disabled="loggedIn"
|
||
|
autocomplete="current-password"
|
||
|
variant="outlined"
|
||
|
color="primary"
|
||
|
class="pt-4"
|
||
|
/>
|
||
|
</VForm>
|
||
|
<p v-if="loggedIn">
|
||
|
Logged in<br>{{ userInfo }}
|
||
|
</p>
|
||
|
</template>
|
||
|
<template #actions>
|
||
|
<VBtn
|
||
|
v-if="!loggedIn"
|
||
|
color="primary"
|
||
|
:disabled="loggedIn || loading"
|
||
|
@click="submit"
|
||
|
>
|
||
|
Login
|
||
|
</VBtn>
|
||
|
<VBtn
|
||
|
v-if="loggedIn"
|
||
|
color="primary"
|
||
|
:disabled="!loggedIn"
|
||
|
@click="logout"
|
||
|
>
|
||
|
Logout
|
||
|
</VBtn>
|
||
|
</template>
|
||
|
</VCard>
|
||
|
</template>
|