-
+
{OTP_SLOTS.map((index) => (
-
+
))}
diff --git a/apps/sim/app/(interfaces)/chat/components/auth/email/email-auth.tsx b/apps/sim/app/(interfaces)/chat/components/auth/email/email-auth.tsx
index 7972106bfc9..190dfbaf917 100644
--- a/apps/sim/app/(interfaces)/chat/components/auth/email/email-auth.tsx
+++ b/apps/sim/app/(interfaces)/chat/components/auth/email/email-auth.tsx
@@ -34,13 +34,17 @@ const validateEmailField = (emailValue: string): string[] => {
export default function EmailAuth({ identifier }: EmailAuthProps) {
const [email, setEmail] = useState('')
- const [authError, setAuthError] = useState(null)
+ const [authError, setAuthError] = useState<{
+ kind: 'verification' | 'request'
+ message: string
+ } | null>(null)
const [emailErrors, setEmailErrors] = useState([])
const hasEmailError = emailErrors.length > 0
const [showOtpVerification, setShowOtpVerification] = useState(false)
const [otpValue, setOtpValue] = useState('')
const [countdown, setCountdown] = useState(0)
+ const isInvalidOtp = authError?.kind === 'verification'
const requestOtp = useChatEmailOtpRequest(identifier)
const verifyOtp = useChatEmailOtpVerify(identifier)
@@ -89,7 +93,10 @@ export default function EmailAuth({ identifier }: EmailAuthProps) {
await verifyOtp.mutateAsync({ email, otp: codeToVerify })
} catch (error) {
logger.error('Error verifying OTP:', error)
- setAuthError(toError(error).message || 'Invalid verification code')
+ setAuthError({
+ kind: 'verification',
+ message: toError(error).message || 'Invalid verification code',
+ })
}
}
@@ -102,7 +109,10 @@ export default function EmailAuth({ identifier }: EmailAuthProps) {
setOtpValue('')
} catch (error) {
logger.error('Error resending OTP:', error)
- setAuthError(toError(error).message || 'Failed to resend verification code')
+ setAuthError({
+ kind: 'request',
+ message: toError(error).message || 'Failed to resend verification code',
+ })
setCountdown(0)
}
}
@@ -143,7 +153,7 @@ export default function EmailAuth({ identifier }: EmailAuthProps) {
autoCorrect='off'
value={email}
onChange={handleEmailChange}
- className='h-[34px]'
+ size='lg'
error={Boolean(hasEmailError)}
/>
{hasEmailError && (
@@ -181,15 +191,12 @@ export default function EmailAuth({ identifier }: EmailAuthProps) {
}
}}
disabled={verifyOtp.isPending}
- className={cn('gap-2', authError && 'otp-error')}
+ className={cn('gap-2', isInvalidOtp && 'otp-error')}
+ aria-invalid={isInvalidOtp}
>
{[0, 1, 2, 3, 4, 5].map((index) => (
-
+
))}
@@ -197,7 +204,7 @@ export default function EmailAuth({ identifier }: EmailAuthProps) {
{authError && (
-
{authError}
+
{authError.message}
)}
diff --git a/apps/sim/app/(interfaces)/chat/components/auth/password/password-auth.tsx b/apps/sim/app/(interfaces)/chat/components/auth/password/password-auth.tsx
index cd49a26fa28..36467bc6287 100644
--- a/apps/sim/app/(interfaces)/chat/components/auth/password/password-auth.tsx
+++ b/apps/sim/app/(interfaces)/chat/components/auth/password/password-auth.tsx
@@ -72,7 +72,6 @@ export default function PasswordAuth({ identifier }: PasswordAuthProps) {
placeholder='Enter password'
value={password}
onChange={handlePasswordChange}
- className='h-[34px]'
error={hasPasswordError}
/>
{error ?
{error}
: null}
diff --git a/apps/sim/app/f/[token]/public-file-email-auth.tsx b/apps/sim/app/f/[token]/public-file-email-auth.tsx
index 8d237ed9ff5..198fea32ae5 100644
--- a/apps/sim/app/f/[token]/public-file-email-auth.tsx
+++ b/apps/sim/app/f/[token]/public-file-email-auth.tsx
@@ -28,8 +28,12 @@ export function PublicFileEmailAuth({ token }: PublicFileEmailAuthProps) {
const [email, setEmail] = useState('')
const [otp, setOtp] = useState('')
const [sent, setSent] = useState(false)
- const [error, setError] = useState
(null)
+ const [error, setError] = useState<{
+ kind: 'verification' | 'request'
+ message: string
+ } | null>(null)
const [countdown, setCountdown] = useState(0)
+ const isInvalidOtp = error?.kind === 'verification'
useEffect(() => {
if (countdown <= 0) return
@@ -39,7 +43,7 @@ export function PublicFileEmailAuth({ token }: PublicFileEmailAuthProps) {
const sendCode = async () => {
if (!quickValidateEmail(normalizeEmail(email)).isValid) {
- setError('Please enter a valid email address.')
+ setError({ kind: 'request', message: 'Please enter a valid email address.' })
return
}
setError(null)
@@ -48,7 +52,10 @@ export function PublicFileEmailAuth({ token }: PublicFileEmailAuthProps) {
setSent(true)
setOtp('')
} catch (err) {
- setError(getErrorMessage(err, 'Failed to send verification code'))
+ setError({
+ kind: 'request',
+ message: getErrorMessage(err, 'Failed to send verification code'),
+ })
}
}
@@ -59,7 +66,7 @@ export function PublicFileEmailAuth({ token }: PublicFileEmailAuthProps) {
await verifyOtp.mutateAsync({ email: normalizeEmail(email), otp: code })
router.refresh()
} catch (err) {
- setError(getErrorMessage(err, 'Invalid verification code'))
+ setError({ kind: 'verification', message: getErrorMessage(err, 'Invalid verification code') })
}
}
@@ -71,7 +78,10 @@ export function PublicFileEmailAuth({ token }: PublicFileEmailAuthProps) {
setError(null)
} catch (err) {
setCountdown(0)
- setError(getErrorMessage(err, 'Failed to resend verification code'))
+ setError({
+ kind: 'request',
+ message: getErrorMessage(err, 'Failed to resend verification code'),
+ })
}
}
@@ -104,10 +114,10 @@ export function PublicFileEmailAuth({ token }: PublicFileEmailAuthProps) {
setEmail(e.target.value)
setError(null)
}}
- className='h-[34px]'
+ size='lg'
error={Boolean(error)}
/>
- {error ? {error}
: null}
+ {error ? {error.message}
: null}