import { createFileRoute, Link } from '@tanstack/react-router'; import { z } from 'zod'; import { useEffect, useState } from 'react'; import { CheckCircle, XCircle, Loader2 } from 'lucide-react'; import { apiClient } from '@/infrastructure/http/ApiClient'; import { forceTokenRefresh } from '@/infrastructure/http/auth-refresh'; import { VERIFY_EMAIL } from '@archer/api-interface/endpoints/customer-api'; const verifyEmailSearchSchema = z.object({ token: z.string(), }); export const Route = createFileRoute('/auth/verify-email')({ validateSearch: verifyEmailSearchSchema, component: VerifyEmailPage, }); function VerifyEmailPage() { const { token } = Route.useSearch(); const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading'); const [message, setMessage] = useState(''); useEffect(() => { async function verify() { try { const res = await apiClient.post<{ message?: string }>(VERIFY_EMAIL.path, { token }); // Force a fresh token round-trip so the AuthenticatedUser snapshot // rebuilds from current DB state (emailVerified flips). Swallow the // refresh error: anonymous-browser verify (link clicked elsewhere) // has no refresh token; the success message still renders, the next // /auth/login hydrates correctly. try { await forceTokenRefresh(); } catch { /* anonymous verify */ } setStatus('success'); setMessage(res.message || 'Email verified successfully.'); } catch (err: any) { setStatus('error'); setMessage(err?.response?.data?.message || 'Verification failed. The link may be expired or invalid.'); } } verify(); }, [token]); return (
{status === 'loading' && ( <>

Verifying your email...

Please wait a moment.

)} {status === 'success' && ( <>

Email Verified

{message}

Go to Dashboard )} {status === 'error' && ( <>

Verification Failed

{message}

Go to Login )}
); }