import { useEffect, useRef, useState } from 'react'; import { Turnstile } from '@marsidev/react-turnstile'; import { Callout, CalloutDescription } from '@/components/ui/callout'; import { AlertCircle, RefreshCw } from 'lucide-react'; import { Button } from '@/components/ui/button'; interface TurnstileCaptchaProps { onSuccess: (token: string) => void; onError?: (error: string) => void; onExpire?: () => void; siteKey?: string; theme?: 'light' | 'dark' | 'auto'; size?: 'normal' | 'compact'; className?: string; } export function TurnstileCaptcha({ onSuccess, onError, onExpire, siteKey = import.meta.env.VITE_TURNSTILE_SITE_KEY, theme = 'auto', size = 'normal', className = '' }: TurnstileCaptchaProps) { const [error, setError] = useState(null); const [loading, setLoading] = useState(true); const [key, setKey] = useState(0); const turnstileRef = useRef(null); const handleSuccess = (token: string) => { setError(null); setLoading(false); onSuccess(token); }; const handleError = (errorCode: string) => { setLoading(false); const errorMessage = getErrorMessage(errorCode); setError(errorMessage); onError?.(errorMessage); }; const handleExpire = () => { setError('CAPTCHA expired. Please try again.'); onExpire?.(); }; const handleLoad = () => { setLoading(false); setError(null); }; const resetCaptcha = () => { setKey(prev => prev + 1); setError(null); setLoading(true); }; const getErrorMessage = (errorCode: string): string => { switch (errorCode) { case 'network-error': return 'Network error. Please check your connection and try again.'; case 'timeout': return 'CAPTCHA timed out. Please try again.'; case 'invalid-sitekey': return 'Invalid site configuration. Please contact support.'; case 'token-already-spent': return 'CAPTCHA token already used. Please refresh and try again.'; default: return 'CAPTCHA verification failed. Please try again.'; } }; // Monitor for initialization failures useEffect(() => { if (loading) { const timeout = setTimeout(() => { setLoading(false); }, 5000); // 5 second timeout return () => clearTimeout(timeout); } }, [loading]); if (!siteKey) { return ( CAPTCHA is not configured. Please set VITE_TURNSTILE_SITE_KEY environment variable. ); } return (
{loading && (
Loading CAPTCHA...
)}
{error && ( {error} )}
); }