<script setup>
// Вход через gnexus-auth. Скелет: пока токен вставляется вручную (dev).
// TODO(#32): полноценный OAuth2 Authorization Code + PKCE через JS-клиент
// gnexus-auth (packages/auth-client, docs 18-20) — redirect на authorize,
// callback с обменом кода, refresh-ротация на стороне SPA.
import { ref } from "vue";
import { useRouter } from "vue-router";
import { GnButton, GnStatusCard } from "gnexus-ui-kit/vue";
import { adminMe, setToken } from "../api.js";
const router = useRouter();
const token = ref("");
const error = ref("");
const busy = ref(false);
async function signIn() {
error.value = "";
busy.value = true;
setToken(token.value.trim());
try {
const me = await adminMe();
if (me.system_role === "admin" || me.system_role === "superadmin") {
await router.push(router.currentRoute.value.query.next || "/dashboard");
} else {
await router.push("/denied");
}
} catch (ex) {
error.value = ex.status === 403 ? "Недостаточно прав: роль admin и выше" : `Вход не удался: ${ex.message}`;
} finally {
busy.value = false;
}
}
</script>
<template>
<div class="login-page">
<div class="login-panel">
<h2 class="login-title">Synapse Admin</h2>
<p class="login-note">
Вход через gnexus-auth. Скелет: вставьте access-токен (dev-режим), финальный
OAuth-поток — в задаче #32.
</p>
<input
v-model="token"
class="login-input"
type="password"
placeholder="access token"
@keyup.enter="signIn"
/>
<GnButton variant="primary" icon="ph-sign-in" :loading="busy" @click="signIn">
Войти
</GnButton>
<GnStatusCard v-if="error" variant="error" icon="ph-warning" :text="error" />
</div>
</div>
</template>
<style scoped>
.login-page {
min-height: 100vh;
display: grid;
place-items: center;
padding: var(--gn-space-4);
}
.login-panel {
background: var(--gn-surface-panel-muted);
border: var(--gn-border-width-base) var(--gn-border-style-base) var(--gn-border-color-muted);
border-left-width: var(--gn-border-width-accent);
padding: var(--gn-space-6);
display: flex;
flex-direction: column;
gap: var(--gn-space-4);
max-width: 420px;
width: 100%;
}
.login-title {
font-size: var(--gn-font-size-lg);
font-weight: var(--gn-font-weight-bold);
text-transform: uppercase;
}
.login-note {
font-size: var(--gn-font-size-xs);
color: var(--gn-color-text-medium);
}
.login-input {
background: var(--gn-surface-base);
color: var(--gn-color-text-light);
border: var(--gn-border-width-base) var(--gn-border-style-base) var(--gn-border-color-muted);
padding: var(--gn-space-2) var(--gn-space-3);
font-family: var(--gn-font-family-base);
}
.login-input:focus-visible {
outline: var(--gn-focus-ring);
}
</style>