91 lines
2.4 KiB
Vue
91 lines
2.4 KiB
Vue
<script setup lang="ts">
|
|
import type { AuthTokens } from "@vmall/shared";
|
|
|
|
definePageMeta({ layout: false });
|
|
|
|
const { $api } = useNuxtApp();
|
|
const session = useSessionStore();
|
|
const { t } = useI18n();
|
|
|
|
const email = ref("admin@vmall.local");
|
|
const password = ref("admin1234");
|
|
const loading = ref(false);
|
|
const errorMessage = ref("");
|
|
|
|
async function submit(): Promise<void> {
|
|
if (!email.value.trim() || !password.value) {
|
|
errorMessage.value = t("common.required");
|
|
return;
|
|
}
|
|
|
|
loading.value = true;
|
|
errorMessage.value = "";
|
|
try {
|
|
const auth: AuthTokens = await $api.login(email.value.trim(), password.value);
|
|
if (auth.user.role !== "platform_admin") {
|
|
errorMessage.value = t("auth.wrongRole");
|
|
return;
|
|
}
|
|
session.setAuth(auth);
|
|
await navigateTo("/");
|
|
} catch (error: unknown) {
|
|
errorMessage.value = error instanceof Error ? error.message : t("common.error");
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="login-shell">
|
|
<form class="card form-narrow login-card" @submit.prevent="submit">
|
|
<p class="eyebrow">{{ $t("common.appName") }} · Admin</p>
|
|
<h1 class="page-title">{{ $t("auth.welcome") }}</h1>
|
|
<p class="muted">{{ $t("admin.dashboardTitle") }}</p>
|
|
<div class="field">
|
|
<label for="email">{{ $t("common.email") }}</label>
|
|
<input id="email" v-model="email" type="email" autocomplete="username" required />
|
|
</div>
|
|
<div class="field">
|
|
<label for="password">{{ $t("common.password") }}</label>
|
|
<input id="password" v-model="password" type="password" autocomplete="current-password" required />
|
|
</div>
|
|
<p v-if="errorMessage" class="error-text" role="alert">{{ errorMessage }}</p>
|
|
<button class="btn primary submit-button" type="submit" :disabled="loading">
|
|
{{ loading ? $t("common.loading") : $t("common.login") }}
|
|
</button>
|
|
<p class="muted hint">{{ $t("auth.adminHint") }}</p>
|
|
</form>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.login-shell {
|
|
min-height: 100vh;
|
|
display: grid;
|
|
place-items: center;
|
|
padding: 24px;
|
|
}
|
|
.login-card {
|
|
width: min(100%, 420px);
|
|
margin: 0;
|
|
}
|
|
.eyebrow {
|
|
color: var(--primary);
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.08em;
|
|
margin: 0 0 10px;
|
|
text-transform: uppercase;
|
|
}
|
|
.submit-button {
|
|
width: 100%;
|
|
justify-content: center;
|
|
}
|
|
.hint {
|
|
font-size: 12px;
|
|
margin: 16px 0 0;
|
|
text-align: center;
|
|
}
|
|
</style>
|