- Add void operator to async calls in $effect() blocks to satisfy noFloatingPromises lint rule: - passkey/+page.svelte: void authenticate() - verify/+page.svelte: void verifyEmail() - Apply biome formatter import reorganization across auth files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
144 lines
3.6 KiB
Svelte
144 lines
3.6 KiB
Svelte
<script lang="ts">
|
|
import { CheckCircle2, Loader2, Mail, XCircle } from "@lucide/svelte";
|
|
import { toast } from "svelte-sonner";
|
|
import { goto } from "$app/navigation";
|
|
import { page } from "$app/state";
|
|
import { api } from "$lib/api/client";
|
|
import { ErrorAlert } from "$lib/components/auth";
|
|
import { Button } from "$lib/components/ui/button";
|
|
|
|
/**
|
|
* Email verification callback page
|
|
* Automatically verifies the email token from URL on mount
|
|
* Redirects to dashboard on success
|
|
*/
|
|
|
|
let isVerifying = $state(true);
|
|
let error = $state("");
|
|
|
|
const token = $derived(page.url.searchParams.get("token"));
|
|
|
|
/**
|
|
* Verify email with the token from URL
|
|
*/
|
|
async function verifyEmail(): Promise<void> {
|
|
if (!token) {
|
|
error = "No verification token provided";
|
|
isVerifying = false;
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await api.auth.verifyEmail({ token });
|
|
toast.success("Email verified successfully!");
|
|
goto("/performance");
|
|
} catch (e) {
|
|
error = e instanceof Error ? e.message : "Verification failed";
|
|
} finally {
|
|
isVerifying = false;
|
|
}
|
|
}
|
|
|
|
// Auto-verify on mount
|
|
$effect(() => {
|
|
if (token) {
|
|
void verifyEmail();
|
|
} else {
|
|
error = "No verification token provided";
|
|
isVerifying = false;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Resend verification email
|
|
*/
|
|
async function resendVerification(): Promise<void> {
|
|
try {
|
|
await api.auth.resendVerificationEmail();
|
|
toast.success("Verification email sent! Check your inbox.");
|
|
error = "";
|
|
} catch (e) {
|
|
const message =
|
|
e instanceof Error ? e.message : "Failed to send verification email";
|
|
toast.error(message);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Verify Email | Publisher Dashboard</title>
|
|
<meta name="description" content="Verify your email address" />
|
|
</svelte:head>
|
|
|
|
<div class="space-y-6">
|
|
<!-- Header -->
|
|
<div class="space-y-4 text-center">
|
|
<div class="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-primary/10">
|
|
{#if isVerifying}
|
|
<Mail class="h-8 w-8 animate-pulse text-primary" />
|
|
{:else if error}
|
|
<XCircle class="h-8 w-8 text-destructive" />
|
|
{:else}
|
|
<CheckCircle2 class="h-8 w-8 text-green-600" />
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<h1 class="text-2xl font-semibold tracking-tight">
|
|
{#if isVerifying}
|
|
Verifying your email...
|
|
{:else if error}
|
|
Verification failed
|
|
{:else}
|
|
Email verified!
|
|
{/if}
|
|
</h1>
|
|
|
|
<p class="text-sm text-muted-foreground">
|
|
{#if isVerifying}
|
|
Please wait while we verify your email address
|
|
{:else if error}
|
|
We could not verify your email address
|
|
{:else}
|
|
Redirecting to your dashboard...
|
|
{/if}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Loading indicator -->
|
|
{#if isVerifying}
|
|
<div class="flex items-center justify-center gap-2 text-sm text-muted-foreground">
|
|
<Loader2 class="h-4 w-4 animate-spin" />
|
|
<span>Verifying...</span>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Error Alert -->
|
|
{#if error}
|
|
<ErrorAlert message={error} />
|
|
|
|
<!-- Actions -->
|
|
<div class="space-y-3">
|
|
{#if token}
|
|
<Button class="h-10 w-full" onclick={verifyEmail}>
|
|
Try again
|
|
</Button>
|
|
{/if}
|
|
|
|
<Button variant="outline" class="h-10 w-full" onclick={resendVerification}>
|
|
Request new verification link
|
|
</Button>
|
|
|
|
<div class="text-center">
|
|
<a
|
|
href="/auth/login"
|
|
class="text-sm text-muted-foreground underline underline-offset-4 hover:text-foreground"
|
|
>
|
|
Back to login
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|