mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2025-11-30 03:18:02 +08:00
chore: fix check email loading state (#93)
* chore: fix check email loading state * chore: add disabled state
This commit is contained in:
@@ -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."
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
setError(e.message);
|
||||
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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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>
|
||||
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user