| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- "use client";
- /**
- * Magic-link landing page.
- * Briven emails: {appOrigin}/auth/verify?preAuthSessionId=…&linkCode=…&deviceId=…
- */
- import Link from "next/link";
- import { useEffect, useState } from "react";
- import { consumeMagicLink } from "@/lib/magic-link";
- export default function MagicLinkVerifyPage() {
- const [message, setMessage] = useState("Signing you in…");
- const [failed, setFailed] = useState(false);
- useEffect(() => {
- let cancelled = false;
- async function run() {
- const params = new URLSearchParams(window.location.search);
- const preAuthSessionId = params.get("preAuthSessionId") || "";
- const linkCode = params.get("linkCode") || "";
- const deviceId = params.get("deviceId") || "";
- if (!preAuthSessionId || !linkCode || !deviceId) {
- if (!cancelled) {
- setFailed(true);
- setMessage(
- "This sign-in link is incomplete. Go back to sign in and request a new magic link.",
- );
- }
- return;
- }
- const res = await consumeMagicLink({
- preAuthSessionId,
- deviceId,
- linkCode,
- });
- if (cancelled) return;
- if (res.ok) {
- setMessage("Signed in. Taking you to your dashboard…");
- window.dispatchEvent(new Event("krypco-auth-change"));
- const next =
- sessionStorage.getItem("krypco_magic_redirect") ||
- params.get("next") ||
- "/portal/dashboard";
- sessionStorage.removeItem("krypco_magic_redirect");
- const safe =
- next.startsWith("/") && !next.startsWith("//")
- ? next
- : "/portal/dashboard";
- window.location.replace(safe);
- return;
- }
- setFailed(true);
- setMessage(
- res.message ||
- "This sign-in link is invalid or expired. Request a new one.",
- );
- }
- void run();
- return () => {
- cancelled = true;
- };
- }, []);
- return (
- <main className="flex min-h-screen items-center justify-center bg-background px-4 text-foreground">
- <div className="w-full max-w-md rounded-2xl border border-border bg-card p-8 text-center shadow-sm">
- <p
- className="text-sm leading-relaxed text-foreground"
- role={failed ? "alert" : "status"}
- >
- {message}
- </p>
- {failed ? (
- <p className="mt-6 text-sm">
- <Link
- href="/portal/sign-in"
- className="text-accent-hover underline-offset-4 hover:underline"
- >
- Back to sign in
- </Link>
- </p>
- ) : null}
- </div>
- </main>
- );
- }
|