'use client' import { useEffect, useState } from 'react' import { cn, Input, InputOTP, InputOTPGroup, InputOTPSlot, Label } from '@sim/emcn' import { createLogger } from '@sim/logger' import { toError } from '@sim/utils/errors' import { quickValidateEmail } from '@/lib/messaging/email/validation' import { AuthSubmitButton } from '@/app/(auth)/components' import { AUTH_TEXT_LINK } from '@/app/(auth)/components/auth-button-classes' import { useChatEmailOtpRequest, useChatEmailOtpVerify } from '@/hooks/queries/chats' const logger = createLogger('EmailAuth') interface EmailAuthProps { identifier: string } const validateEmailField = (emailValue: string): string[] => { const errors: string[] = [] if (!emailValue || !emailValue.trim()) { errors.push('Email is required.') return errors } const validation = quickValidateEmail(emailValue.trim().toLowerCase()) if (!validation.isValid) { errors.push(validation.reason || 'Please enter a valid email address.') } return errors } export default function EmailAuth({ identifier }: EmailAuthProps) { const [email, setEmail] = useState('') const [authError, setAuthError] = useState(null) const [emailErrors, setEmailErrors] = useState([]) const [showEmailValidationError, setShowEmailValidationError] = useState(false) const [showOtpVerification, setShowOtpVerification] = useState(false) const [otpValue, setOtpValue] = useState('') const [countdown, setCountdown] = useState(0) const requestOtp = useChatEmailOtpRequest(identifier) const verifyOtp = useChatEmailOtpVerify(identifier) useEffect(() => { if (countdown <= 0) return const timer = setTimeout(() => setCountdown((c) => c - 1), 1000) return () => clearTimeout(timer) }, [countdown]) const handleEmailChange = (e: React.ChangeEvent) => { const newEmail = e.target.value setEmail(newEmail) const errors = validateEmailField(newEmail) setEmailErrors(errors) setShowEmailValidationError(false) } const handleSendOtp = async () => { const emailValidationErrors = validateEmailField(email) setEmailErrors(emailValidationErrors) setShowEmailValidationError(emailValidationErrors.length > 0) if (emailValidationErrors.length > 0) { return } setAuthError(null) try { await requestOtp.mutateAsync({ email }) setShowOtpVerification(true) } catch (error) { logger.error('Error sending OTP:', error) setEmailErrors([toError(error).message || 'Failed to send verification code']) setShowEmailValidationError(true) } } const handleVerifyOtp = async (otp?: string) => { const codeToVerify = otp || otpValue if (!codeToVerify || codeToVerify.length !== 6) { return } setAuthError(null) try { await verifyOtp.mutateAsync({ email, otp: codeToVerify }) } catch (error) { logger.error('Error verifying OTP:', error) setAuthError(toError(error).message || 'Invalid verification code') } } const handleResendOtp = async () => { setAuthError(null) setCountdown(30) try { await requestOtp.mutateAsync({ email }) setOtpValue('') } catch (error) { logger.error('Error resending OTP:', error) setAuthError(toError(error).message || 'Failed to resend verification code') setCountdown(0) } } return (

{showOtpVerification ? 'Verify Your Email' : 'Email Verification'}

{showOtpVerification ? `A verification code has been sent to ${email}` : 'This chat requires email verification'}

{!showOtpVerification ? (
{ e.preventDefault() handleSendOtp() }} className='space-y-6' >
0 && 'border-[var(--text-error)] focus:border-[var(--text-error)]' )} /> {showEmailValidationError && emailErrors.length > 0 && (
{emailErrors.map((error) => (

{error}

))}
)}
Continue
) : (

Enter the 6-digit code to verify your account. If you don't see it in your inbox, check your spam folder.

{ setOtpValue(value) if (value.length === 6) { handleVerifyOtp(value) } }} disabled={verifyOtp.isPending} className={cn('gap-2', authError && 'otp-error')} > {[0, 1, 2, 3, 4, 5].map((index) => ( ))}
{authError && (

{authError}

)} handleVerifyOtp()} disabled={otpValue.length !== 6} loading={verifyOtp.isPending} loadingLabel='Verifying…' > Verify Email

Didn't receive a code?{' '} {countdown > 0 ? ( Resend in{' '} {countdown}s ) : ( )}

)}
) }