'use client'; import React, { useState, useEffect } from 'react'; import { API_PATHS } from '../types/api'; interface EmailVerificationProps { email?: string; onVerified?: () => void; onVerificationSent?: () => void; className?: string; } export default function EmailVerification({ email, onVerified, onVerificationSent, className = '', }: EmailVerificationProps) { const [isVerified, setIsVerified] = useState(null); const [isSending, setIsSending] = useState(false); const [isResending, setIsResending] = useState(false); const [countdown, setCountdown] = useState(0); const [error, setError] = useState(null); const [message, setMessage] = useState(null); // Check verification status on mount useEffect(() => { checkVerificationStatus(); }, []); // Handle countdown for resend button useEffect(() => { if (countdown > 0) { const timer = setTimeout(() => setCountdown(countdown - 1), 1000); return () => clearTimeout(timer); } }, [countdown]); // Check email verification status const checkVerificationStatus = async () => { try { const response = await fetch('/api/auth/email-status', { headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { // If endpoint doesn't exist, assume unverified setIsVerified(false); return; } const data = await response.json(); setIsVerified(data.isVerified); } catch (err) { // Assume unverified if we can't check setIsVerified(false); } }; // Send verification email const sendVerificationEmail = async (isResend = false) => { try { if (isResend) { setIsResending(true); } else { setIsSending(true); } setError(null); setMessage(null); const response = await fetch(API_PATHS.AUTH_VERIFY_EMAIL, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email, }), }); if (!response.ok) { throw new Error('Failed to send verification email'); } setMessage('Verification email sent! Please check your inbox.'); onVerificationSent?.(); // Start countdown for resend setCountdown(60); if (!isResend) { // Poll for verification status const pollInterval = setInterval(async () => { try { const statusResponse = await fetch('/api/auth/email-status', { headers: { 'Content-Type': 'application/json', }, }); if (statusResponse.ok) { const data = await statusResponse.json(); if (data.isVerified) { setIsVerified(true); clearInterval(pollInterval); onVerified?.(); } } } catch (err) { // Continue polling } }, 5000); // Stop polling after 5 minutes setTimeout(() => clearInterval(pollInterval), 300000); } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to send verification email'); } finally { setIsSending(false); setIsResending(false); } }; // Handle manual verification (user enters code) const handleManualVerification = async (code: string) => { try { setError(null); setMessage(null); const response = await fetch(API_PATHS.AUTH_CONFIRM_EMAIL, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ code, email, }), }); if (!response.ok) { const data = await response.json(); throw new Error(data.error || 'Invalid verification code'); } setIsVerified(true); setMessage('Email verified successfully!'); onVerified?.(); } catch (err) { setError(err instanceof Error ? err.message : 'Invalid verification code'); } }; // Loading state if (isVerified === null) { return (
); } // Verified state if (isVerified) { return (

Email verified

Your email address {email} has been verified successfully.

); } // Unverified state return (

Email verification required

Please verify your email address {email ? `(${email})` : ''} to access all features.

{/* Error message */} {error && (

{error}

)} {/* Success message */} {message && (

{message}

)} {/* Send verification button */} {!isSending && ( )} {/* Loading state */} {isSending && (
Sending...
)} {/* Resend option */} {countdown > 0 ? (

Resend available in {countdown} seconds

) : ( )} {/* Manual verification option */}
{/* Help text */}

Didn't receive the email?

  • • Check your spam or junk folder
  • • Make sure the email address is correct
  • • Wait a few minutes for delivery
  • • Try clicking the resend button above
); } // Manual verification form component function ManualVerificationForm({ onVerify }: { onVerify: (code: string) => void }) { const [code, setCode] = useState(''); const [isVerifying, setIsVerifying] = useState(false); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (code.trim()) { setIsVerifying(true); onVerify(code.trim()); setTimeout(() => setIsVerifying(false), 2000); // Reset after delay } }; return (

Or enter verification code manually:

setCode(e.target.value)} placeholder="Enter 6-digit code" maxLength={6} className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-center tracking-widest text-lg" pattern="[0-9]{6}" />
); }