chore: fix check email loading state (#93)

* chore: fix check email loading state

* chore: add disabled state
This commit is contained in:
Kilu.He
2025-04-14 13:41:43 +08:00
committed by GitHub
parent 60627857fb
commit c6a86e08e2
7 changed files with 39 additions and 33 deletions

View File

@@ -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."
}

View File

@@ -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,
});
}

View File

@@ -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<string>('');
const [isEnter, setEnter] = useState<boolean>(false);
const [code, setCode] = useState<string>('');
const [loading, setLoading] = React.useState<boolean>(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);
if (e.code === 403) {
setError(t('invalidOTPCode'));
} else {
setError(e.message);
}
} finally {
setLoading(false);
toast.dismiss(id);
}
};
return (
<div className={'flex flex-col gap-5 items-center justify-center w-full px-4'}>
<div className={'flex text-text-primary flex-col gap-5 items-center justify-center w-full px-4'}>
<div
onClick={() => {
window.location.href = '/';
@@ -46,10 +58,10 @@ function CheckEmail ({ email, redirectTo }: {
<Logo className={'h-10 w-10'} />
</div>
<div className={'text-xl text-text-primary font-semibold'}>
{t('checkYourEmail')}
{isEnter ? t('enterCode') : t('checkYourEmail')}
</div>
<div className={'flex text-sm w-[320px] text-center items-center flex-col justify-center'}>
<div className={'font-normal'}>{t('checkEmailTip')}</div>
<div className={'font-normal'}>{isEnter ? t('checkCodeTip') : t('checkEmailTip')}</div>
<div className={'font-semibold'}>
{email}
</div>
@@ -77,21 +89,10 @@ function CheckEmail ({ email, redirectTo }: {
<Button
onClick={handleSubmit}
disabled={loading}
size={'lg'}
className={'w-[320px]'}
>
{loading ? (
<>
<Progress
size={'sm'}
variant={'theme'}
/>
{t('editor.loading')}...
</>
) : (
t('continueToSignIn')
)}
{t('continueToSignIn')}
</Button>
</div>
) : <Button
@@ -103,12 +104,11 @@ function CheckEmail ({ email, redirectTo }: {
</Button>}
<Button
size={'lg'}
variant={'ghost'}
variant={'link'}
onClick={() => {
window.location.href = `/login?redirectTo=${redirectTo}`;
}}
className={'w-[320px] hover:bg-transparent text-text-theme hover:text-text-theme-hover h-5'}
className={'w-[320px]'}
>
{t('backToLogin')}
</Button>

View File

@@ -10,7 +10,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) {
const { t } = useTranslation();
return (
<div className={'py-10 flex flex-col h-full items-center justify-between gap-5 px-4'}>
<div className={'py-10 text-text-primary flex flex-col h-full items-center justify-between gap-5 px-4'}>
<div className={'flex flex-1 flex-col items-center justify-center w-full gap-5'}>
<div
onClick={() => {
@@ -37,7 +37,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) {
<a
href={'https://appflowy.com/terms'}
target={'_blank'}
className={'text-text-theme underline'}
className={'text-text-secondary underline'}
>
{t('web.termOfUse')}
</a>{' '}
@@ -45,7 +45,7 @@ export function Login ({ redirectTo }: { redirectTo: string }) {
<a
href={'https://appflowy.com/privacy'}
target={'_blank'}
className={'text-text-theme underline'}
className={'text-text-secondary underline'}
>
{t('web.privacyPolicy')}
</a>
@@ -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'
}
>
<span>{t('web.visitOurWebsite')}</span>

View File

@@ -124,9 +124,9 @@ function LoginProvider ({ redirectTo }: { redirectTo: string }) {
whileTap="tap"
>
<Button
variant={'ghost'}
variant={'link'}
onClick={() => setExpand(true)}
className={'w-full !h-5 text-text-theme hover:bg-transparent hover:text-text-theme-hover'}
className={'w-full'}
>
{t('web.moreOptions')}
</Button>

View File

@@ -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',

View File

@@ -84,9 +84,10 @@ function Input ({
)}
{...props}
/>
<div className={cn('help-text text-xs', variant === 'destructive' && 'text-text-error')}>
{helpText && <div className={cn('help-text text-xs', variant === 'destructive' && 'text-text-error')}>
{helpText}
</div>
</div>}
</div>
);