diff --git a/src/@types/translations/en.json b/src/@types/translations/en.json index 9dc02595..6053c253 100644 --- a/src/@types/translations/en.json +++ b/src/@types/translations/en.json @@ -3097,8 +3097,12 @@ "copiedVideoLink": "Video original link copied to clipboard", "checkYourEmail": "Check your email", "checkEmailTip": "A temporary verification link has been sent. Please check your inbox at", + "checkCodeTip": "A temporary verification code has been sent. Please check your inbox at", "enterCodeManually": "Enter code manually", "backToLogin": "Back to login", "enterCode": "Enter code", - "continueToSignIn": "Continue to sign in" + "continueToSignIn": "Continue to sign in", + "requireCode": "Please enter a valid verification code.", + "signing": "Signing in...", + "invalidOTPCode": "The code is invalid or has expired. Please try again." } diff --git a/src/application/services/js-services/http/gotrue.ts b/src/application/services/js-services/http/gotrue.ts index b875aa8e..9fb198aa 100644 --- a/src/application/services/js-services/http/gotrue.ts +++ b/src/application/services/js-services/http/gotrue.ts @@ -90,8 +90,8 @@ export async function signInOTP ({ emit(EventType.SESSION_INVALID); return Promise.reject({ - code: e.code, - message: e.message, + code: e.response?.data?.code || e.response?.status, + message: e.response?.data?.msg || e.message, }); } diff --git a/src/components/login/CheckEmail.tsx b/src/components/login/CheckEmail.tsx index 21403806..dd558631 100644 --- a/src/components/login/CheckEmail.tsx +++ b/src/components/login/CheckEmail.tsx @@ -1,24 +1,32 @@ 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'; +import { toast } from 'sonner'; function CheckEmail ({ email, redirectTo }: { email: string; redirectTo: string; }) { const { t } = useTranslation(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); const [isEnter, setEnter] = useState(false); const [code, setCode] = useState(''); - const [loading, setLoading] = React.useState(false); const service = useContext(AFConfigContext)?.service; const handleSubmit = async () => { + if (loading) return; + if (!code) { + setError(t('requireCode')); + return; + } + setLoading(true); + const id = toast.loading(t('signing')); try { await service?.signInOTP({ @@ -28,15 +36,19 @@ function CheckEmail ({ email, redirectTo }: { }); // eslint-disable-next-line } catch (e: any) { - console.log(e); - setError(e.message); + if (e.code === 403) { + setError(t('invalidOTPCode')); + } else { + setError(e.message); + } } finally { setLoading(false); + toast.dismiss(id); } }; return ( -
+
{ window.location.href = '/'; @@ -46,10 +58,10 @@ function CheckEmail ({ email, redirectTo }: {
- {t('checkYourEmail')} + {isEnter ? t('enterCode') : t('checkYourEmail')}
-
{t('checkEmailTip')}
+
{isEnter ? t('checkCodeTip') : t('checkEmailTip')}
{email}
@@ -77,21 +89,10 @@ function CheckEmail ({ email, redirectTo }: {
) : diff --git a/src/components/login/Login.tsx b/src/components/login/Login.tsx index dfca16e8..47cd4e0f 100644 --- a/src/components/login/Login.tsx +++ b/src/components/login/Login.tsx @@ -10,7 +10,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) { const { t } = useTranslation(); return ( -
+
{ @@ -37,7 +37,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) { {t('web.termOfUse')} {' '} @@ -45,7 +45,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) { {t('web.privacyPolicy')} @@ -60,7 +60,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) { window.location.href = 'https://appflowy.com'; }} className={ - 'flex w-full cursor-pointer items-center justify-center gap-2 text-xs font-medium text-text-title opacity-60 hover:opacity-100' + 'flex w-full cursor-pointer text-text-secondary items-center justify-center gap-2 text-xs font-medium' } > {t('web.visitOurWebsite')} diff --git a/src/components/login/LoginProvider.tsx b/src/components/login/LoginProvider.tsx index 3611fb20..5a9b5652 100644 --- a/src/components/login/LoginProvider.tsx +++ b/src/components/login/LoginProvider.tsx @@ -124,9 +124,9 @@ function LoginProvider ({ redirectTo }: { redirectTo: string }) { whileTap="tap" > diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 1679cfe9..6bcb3d5d 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -19,6 +19,7 @@ const buttonVariants = cva( 'bg-transparent text-text-error hover:bg-fill-error-select hover:text-text-error-hover border border-border-error-thick hover:border-border-error-thick-hover disabled:text-text-tertiary disabled:border-border-grey-tertiary', ghost: 'hover:bg-fill-primary-alpha-5 text-text-primary disabled:bg-fill-transparent disabled:text-text-tertiary', + link: 'hover:bg-transparent text-text-theme hover:text-text-theme-hover !h-fit', }, size: { sm: 'h-7 text-sm px-4 rounded-300 gap-2 font-normal', diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index fd3676cc..3348c93b 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -84,9 +84,10 @@ function Input ({ )} {...props} /> -
+ {helpText &&
{helpText} -
+
} +
);