128 lines
3.9 KiB
Vue
128 lines
3.9 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import { Dialog, Notify } from 'quasar';
|
|
import { useAuthStore } from '~/stores/auth';
|
|
import { AppwriteException } from 'appwrite';
|
|
|
|
definePageMeta({ public: true, layout: false });
|
|
|
|
const email = ref('');
|
|
const token = ref('');
|
|
const userId = ref<string | undefined>();
|
|
const authStore = useAuthStore();
|
|
|
|
const sendMagicLink = async () => {
|
|
if (!email.value) {
|
|
Dialog.create({ message: 'Please enter your e-mail address.' });
|
|
return;
|
|
}
|
|
try {
|
|
await authStore.createMagicURLSession(email.value);
|
|
Dialog.create({ message: 'Check your e-mail for a magic login link.' });
|
|
} catch {
|
|
Dialog.create({ message: 'An error occurred. Please ask for help in Discord.' });
|
|
}
|
|
};
|
|
|
|
const doTokenLogin = async () => {
|
|
if (!userId.value) {
|
|
try {
|
|
const sessionToken = await authStore.createTokenSession(email.value);
|
|
userId.value = sessionToken.userId;
|
|
Dialog.create({ message: 'Check your e-mail for your login code.' });
|
|
} catch {
|
|
Dialog.create({ message: 'An error occurred. Please ask for help in Discord.' });
|
|
}
|
|
} else {
|
|
const notification = Notify.create({
|
|
type: 'primary',
|
|
position: 'top',
|
|
spinner: true,
|
|
message: 'Logging you in...',
|
|
timeout: 8000,
|
|
group: false,
|
|
});
|
|
try {
|
|
await authStore.tokenLogin(userId.value, token.value);
|
|
notification({ type: 'positive', message: 'Logged in!', timeout: 2000, spinner: false, icon: 'check_circle' });
|
|
await navigateTo('/');
|
|
} catch (error: unknown) {
|
|
if (error instanceof AppwriteException) {
|
|
if (error.type === 'user_session_already_exists') {
|
|
notification({ type: 'positive', message: 'Already logged in!', timeout: 2000, spinner: false, icon: 'check_circle' });
|
|
await navigateTo('/');
|
|
return;
|
|
}
|
|
Dialog.create({ title: 'Login Error!', message: error.message, persistent: true });
|
|
}
|
|
notification({ type: 'negative', message: 'Login failed.', timeout: 2000 });
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<q-layout>
|
|
<q-page-container>
|
|
<q-page class="flex bg-image flex-center">
|
|
<q-card
|
|
v-bind:style="$q.screen.lt.sm ? { width: '80%' } : { width: '30%' }">
|
|
<q-card-section>
|
|
<q-img fit="scale-down" src="/oysqn_logo.png" />
|
|
</q-card-section>
|
|
<q-card-section>
|
|
<div class="text-center q-pt-sm">
|
|
<div class="col text-h6">Log in</div>
|
|
</div>
|
|
</q-card-section>
|
|
<q-form @keydown.enter.prevent="doTokenLogin">
|
|
<q-card-section class="q-gutter-md">
|
|
<q-input
|
|
v-model="email"
|
|
label="E-Mail"
|
|
type="email"
|
|
color="darkblue"
|
|
filled />
|
|
<q-input
|
|
v-if="userId"
|
|
v-model="token"
|
|
label="6-digit code"
|
|
type="number"
|
|
color="darkblue"
|
|
filled />
|
|
</q-card-section>
|
|
</q-form>
|
|
<q-card-section class="q-pa-none">
|
|
<div class="row justify-center q-ma-sm">
|
|
<q-btn
|
|
v-if="!userId"
|
|
type="button"
|
|
@click="sendMagicLink"
|
|
color="secondary"
|
|
label="Send Magic Link"
|
|
style="width: 300px" />
|
|
</div>
|
|
<div class="row justify-center q-ma-sm">
|
|
<q-btn
|
|
type="button"
|
|
@click="doTokenLogin"
|
|
color="primary"
|
|
:label="userId ? 'Login' : 'Send Code'"
|
|
style="width: 300px" />
|
|
</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
</q-page>
|
|
</q-page-container>
|
|
</q-layout>
|
|
</template>
|
|
|
|
<style>
|
|
.bg-image {
|
|
background-image: url('~/assets/oys_lighthouse.jpg');
|
|
background-repeat: no-repeat;
|
|
background-position-x: center;
|
|
background-size: cover;
|
|
}
|
|
</style>
|