<template>
<div class="login-page">
<div class="login-card">
<div class="login-brand">
<img src="/logo-cube-square.svg" alt="Smart Home" class="brand-logo" />
<h1 class="brand-title">Smart Home Server</h1>
</div>
<p class="login-hint text-muted">
You need to sign in to access the smart home dashboard.
</p>
<GnButton
variant="primary"
size="lg"
class="login-btn"
@click="handleLogin"
>
<template #icon>
<i class="ph ph-sign-in" />
</template>
LOGIN WITH GNEXUS
</GnButton>
<p v-if="authStore.isLoading" class="login-loading text-muted">
<i class="ph ph-spinner ph-spin" /> Checking session…
</p>
</div>
</div>
</template>
<script setup>
import { onMounted } from "vue";
import { useRouter } from "vue-router";
import { GnButton } from "gnexus-ui-kit/vue";
import { useAuthStore } from "../../../stores/auth.js";
import {
redirectToOAuth,
getOAuthReturnTo,
} from "../../../api/navigation";
const router = useRouter();
const authStore = useAuthStore();
onMounted(() => {
if (authStore.isAuthenticated) {
router.replace({ name: "areas-favorites" });
}
});
function handleLogin() {
// Same as navi-1: navigate to /auth/login. In the native app Capacitor's
// BridgeWebViewClient intercepts the redirect to the external OAuth host
// and opens it in the system browser via Intent.ACTION_VIEW (full Chrome).
redirectToOAuth(getOAuthReturnTo());
}
</script>
<style scoped>
.login-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 1rem;
}
.login-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
max-width: 360px;
width: 100%;
padding: 2rem;
text-align: center;
}
.login-brand {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.brand-logo {
width: 120px;
height: 120px;
}
.brand-title {
margin: 0;
font-size: 1.25rem;
font-weight: 700;
}
.login-hint {
margin: 0;
font-size: 0.875rem;
line-height: 1.5;
}
.login-btn {
width: 100%;
}
.login-loading {
margin: 0;
font-size: 0.8125rem;
display: flex;
align-items: center;
gap: 0.375rem;
}
</style>