Files
publisher-dashboard/apps/publisher-dashboard/src/routes/auth/verify/+page.svelte
RevIQ 82078b3a05 Fix floating promise lint errors and apply code formatting
- 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>
2026-01-09 16:39:33 +08:00

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>