45 lines
1.6 KiB
Vue
45 lines
1.6 KiB
Vue
<script setup>
|
|
import { nextTick, ref, watch } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
|
|
import { useAuth } from '@/composables/useAuth.js';
|
|
|
|
const router = useRouter();
|
|
const { signIn, isLoading, error } = useAuth();
|
|
const email = ref('');
|
|
const password = ref('');
|
|
const errorMessage = ref(null);
|
|
|
|
watch(error, async (value) => {
|
|
if (!value) return;
|
|
errorMessage.value = value.message;
|
|
await nextTick();
|
|
document.getElementById('login-error')?.focus();
|
|
});
|
|
|
|
async function submit() {
|
|
try {
|
|
await signIn(email.value, password.value);
|
|
await router.push({ name: 'admin-home' });
|
|
} catch {
|
|
// Error is exposed by the auth composable for the live form state.
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<main class="auth-page">
|
|
<form class="auth-panel" @submit.prevent="submit">
|
|
<p class="catalog-kicker">Private workspace</p>
|
|
<h1>Sign in</h1>
|
|
<p class="detail-notes">Manage your collection, images, and listings.</p>
|
|
<label class="fixture-label" for="admin-email">Email</label>
|
|
<input id="admin-email" v-model="email" class="fixture-input" type="email" autocomplete="username" required />
|
|
<label class="fixture-label" for="admin-password">Password</label>
|
|
<input id="admin-password" v-model="password" class="fixture-input" type="password" autocomplete="current-password" required />
|
|
<p v-if="errorMessage" id="login-error" class="state state--error" role="alert" tabindex="-1">{{ errorMessage }}</p>
|
|
<button class="button button--primary" type="submit" :disabled="isLoading">{{ isLoading ? 'Signing in...' : 'Sign in' }}</button>
|
|
</form>
|
|
</main>
|
|
</template>
|