From 60627857fb2eb4a2cea5c490bb41555787d8f182 Mon Sep 17 00:00:00 2001 From: "Kilu.He" <108015703+qinluhe@users.noreply.github.com> Date: Thu, 10 Apr 2025 13:19:31 +0800 Subject: [PATCH] fix: issues of OTP login (#92) --- .../services/js-services/http/gotrue.ts | 24 +++++++++++--- src/components/login/CheckEmail.tsx | 26 ++++++++++++--- src/components/login/MagicLink.tsx | 23 ++++++------- src/components/ui/input.tsx | 33 ++++++++++++------- 4 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/application/services/js-services/http/gotrue.ts b/src/application/services/js-services/http/gotrue.ts index f46eebb3..b875aa8e 100644 --- a/src/application/services/js-services/http/gotrue.ts +++ b/src/application/services/js-services/http/gotrue.ts @@ -56,28 +56,42 @@ export async function signInOTP ({ access_token: string; expires_at: number; refresh_token: string; + code?: number; + msg?: string; }>('/verify', { email, token: code, type: 'recovery', }); - const newToken = response?.data; + const data = response?.data; - if (newToken) { - refreshSessionToken(JSON.stringify(newToken)); + if (data) { + if (data.code !== 0) { + emit(EventType.SESSION_INVALID); + return Promise.reject({ + code: data.code, + message: data.msg, + }); + } + + refreshSessionToken(JSON.stringify(data)); emit(EventType.SESSION_VALID); afterAuth(); } else { emit(EventType.SESSION_INVALID); - return Promise.reject('Failed to sign in otp'); + return Promise.reject({ + code: 'invalid_token', + message: 'Invalid token', + }); } // eslint-disable-next-line } catch (e: any) { + emit(EventType.SESSION_INVALID); return Promise.reject({ code: e.code, - message: e.msg, + message: e.message, }); } diff --git a/src/components/login/CheckEmail.tsx b/src/components/login/CheckEmail.tsx index a7a10445..21403806 100644 --- a/src/components/login/CheckEmail.tsx +++ b/src/components/login/CheckEmail.tsx @@ -1,8 +1,8 @@ -import { notify } from '@/components/_shared/notify'; import { AFConfigContext } from '@/components/main/app.hooks'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Progress } from '@/components/ui/progress'; +import { createHotkey, HOT_KEY_NAME } from '@/utils/hotkeys'; import React, { useContext, useState } from 'react'; import { ReactComponent as Logo } from '@/assets/icons/logo.svg'; import { useTranslation } from 'react-i18next'; @@ -12,6 +12,7 @@ function CheckEmail ({ email, redirectTo }: { redirectTo: string; }) { const { t } = useTranslation(); + const [error, setError] = useState(''); const [isEnter, setEnter] = useState(false); const [code, setCode] = useState(''); const [loading, setLoading] = React.useState(false); @@ -25,8 +26,10 @@ function CheckEmail ({ email, redirectTo }: { redirectTo, code, }); - } catch (e) { - notify.error(t('web.signInError')); + // eslint-disable-next-line + } catch (e: any) { + console.log(e); + setError(e.message); } finally { setLoading(false); } @@ -57,9 +60,19 @@ function CheckEmail ({ email, redirectTo }: { autoFocus size={'md'} className={'w-[320px]'} - onChange={(e) => setCode(e.target.value)} + onChange={(e) => { + setError(''); + setCode(e.target.value); + }} value={code} placeholder={t('enterCode')} + helpText={error} + variant={error ? 'destructive' : 'default'} + onKeyDown={e => { + if (createHotkey(HOT_KEY_NAME.ENTER)(e.nativeEvent)) { + void handleSubmit(); + } + }} /> ); diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 13c5ea98..fd3676cc 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -59,27 +59,36 @@ const inputVariants = cva( export interface InputProps extends Omit, 'size' | 'variant'>, - VariantProps {} + VariantProps { + helpText?: string; +} function Input ({ className, type, variant, size, + helpText, ...props }: InputProps) { return ( - +
+ +
+ {helpText} +
+
+ ); }