/* Copyright (C) 2023-2026 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { useMemo } from 'react' import { ShieldCheck, KeyRound, Loader2 } from 'lucide-react' import { useTranslation } from 'react-i18next' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Dialog } from '@/components/dialog' import type { SecureVerificationState, VerificationMethod, VerificationMethods, } from '../types' interface SecureVerificationDialogProps { open: boolean onOpenChange: (open: boolean) => void methods: VerificationMethods state: SecureVerificationState onVerify: (method: VerificationMethod, code?: string) => void | Promise onCancel: () => void onCodeChange: (code: string) => void onMethodChange: (method: VerificationMethod) => void } export function SecureVerificationDialog({ open, onOpenChange, methods, state, onVerify, onCancel, onCodeChange, onMethodChange, }: SecureVerificationDialogProps) { const { t } = useTranslation() const availableTabs: VerificationMethod[] = useMemo(() => { const tabs: VerificationMethod[] = [] if (methods.has2FA) tabs.push('2fa') if (methods.hasPasskey && methods.passkeySupported) tabs.push('passkey') return tabs }, [methods]) const activeMethod = state.method ?? (availableTabs.length > 0 ? availableTabs[0] : null) const title = state.title ?? (availableTabs.length ? 'Additional verification required' : 'Verification unavailable') const description = state.description ?? (availableTabs.length ? 'Confirm your identity before accessing this sensitive action.' : 'Enable Two-factor Authentication or Passkey in your profile settings to continue.') const handleVerify = () => { if (!activeMethod) return const payload = activeMethod === '2fa' ? state.code : undefined onVerify(activeMethod, payload) } const verifyDisabled = state.loading || (activeMethod === '2fa' && (!state.code.trim() || state.code.length < 6)) return ( {title} } description={description} contentClassName='top-[8vh] max-w-[calc(100%-1.5rem)] translate-y-0 overflow-hidden border-none shadow-xl sm:top-1/2 sm:max-w-md sm:translate-y-[-50%] sm:rounded-xl' headerClassName='border-b pb-4 text-left' titleClassName='flex items-center gap-2 text-lg font-semibold' descriptionClassName='text-left' contentHeight='auto' bodyClassName='px-1 py-1' showCloseButton={!state.loading} footerClassName='bg-muted/30 border-t px-6 py-4 sm:flex-row sm:justify-end' footer={ <> } > {availableTabs.length === 0 ? (

{t( 'Enable Two-factor Authentication or Passkey in your profile to unlock sensitive operations.' )}

) : ( onMethodChange(value as VerificationMethod)} className='gap-4' > {methods.has2FA && ( {t('Authenticator code')} )} {methods.hasPasskey && methods.passkeySupported && ( {t('Passkey')} )}

{t( 'Enter the 6-digit Time-based One-Time Password or 8-character backup code from your authenticator app.' )}

onCodeChange(event.target.value)} placeholder={t('Enter verification code')} disabled={state.loading} autoFocus={activeMethod === '2fa'} onKeyDown={(event) => { if (event.key === 'Enter' && !verifyDisabled) { event.preventDefault() handleVerify() } }} />

{t('Use your Passkey')}

{t( 'We will prompt your device to confirm using biometrics or your hardware key.' )}

{!methods.passkeySupported && (

{t('This device does not support Passkey verification.')}

)}
)}
) }