import { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Loader2, Shield, AlertCircle } from 'lucide-react'; import { twoFactorService } from '@/services/2fa-service'; import { useToast } from '@/hooks/useToast'; import { parseApiError } from '@/utils/apiErrorHandler'; interface TwoFactorVerifyProps { onSuccess: (code: string) => void; onCancel: () => void; } export function TwoFactorVerify({ onSuccess, onCancel }: TwoFactorVerifyProps) { const [code, setCode] = useState(''); const [backupCode, setBackupCode] = useState(''); const [useBackupCode, setUseBackupCode] = useState(false); const [isVerifying, setIsVerifying] = useState(false); const [error, setError] = useState(''); const { toast } = useToast(); const handleVerify = async () => { if (!code && !backupCode) { setError('Please enter a verification code'); return; } try { setIsVerifying(true); setError(''); const verificationCode = useBackupCode ? backupCode : code; // Note: Verification happens in the parent component (login flow) // or via the API endpoint that issued the challenge. // We just pass the code back to the caller. onSuccess(verificationCode); } catch (error: unknown) { const apiError = parseApiError(error); setError(apiError.message); toast({ message: apiError.message, type: 'error', }); } finally { setIsVerifying(false); } }; return ( Two-Factor Authentication Enter the code from your authenticator app Enter the 6-digit code from your authenticator app to continue signing in. {error && ( {error} )} {!useBackupCode ? ( <>
{ setCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setError(''); }} maxLength={6} className="text-center text-2xl tracking-widest" autoFocus />

Lost access?{' '}

) : ( <>
{ setBackupCode(e.target.value); setError(''); }} />

)}
); }