Newer
Older
smart-home-server / webclient / src / features / auth / pages / MobileAuthPage.vue
<template>
  <div class="mobile-auth-page">
    <div class="mobile-auth-card">
      <div class="spinner" />
      <p class="text-muted">{{ statusMessage }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { useAuthStore } from "../../../stores/auth.js";
import { setAccessToken } from "../../../api/auth";

const router = useRouter();
const authStore = useAuthStore();

const statusMessage = ref("Authenticating…");

onMounted(async () => {
  const hash = window.location.hash;
  const queryStart = hash.indexOf("?");

  if (queryStart === -1) {
    statusMessage.value = "Invalid login link. Redirecting…";
    setTimeout(() => router.replace({ name: "login" }), 1500);
    return;
  }

  const params = new URLSearchParams(hash.slice(queryStart + 1));
  const token = params.get("token");
  const expiresIn = params.get("expires_in");

  if (!token) {
    statusMessage.value = "No token received. Redirecting…";
    setTimeout(() => router.replace({ name: "login" }), 1500);
    return;
  }

  // Save token
  setAccessToken(token, expiresIn ? parseInt(expiresIn, 10) : null);

  // Clean URL: remove token from address bar without reloading
  const cleanHash = hash.slice(0, queryStart);
  window.history.replaceState(null, "", cleanHash || "#/");

  statusMessage.value = "Loading profile…";

  try {
    await authStore.init();

    if (authStore.isAuthenticated) {
      router.replace({ name: "areas-favorites" });
    } else {
      statusMessage.value = "Session invalid. Redirecting…";
      setTimeout(() => router.replace({ name: "login" }), 1500);
    }
  } catch {
    statusMessage.value = "Failed to load profile. Redirecting…";
    setTimeout(() => router.replace({ name: "login" }), 1500);
  }
});
</script>

<style scoped>
.mobile-auth-page {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1rem;
}

.mobile-auth-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  text-align: center;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top-color: #12b7f5;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
</style>