0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00

refactor(ui): refactor continue with email or phone (#2418)

This commit is contained in:
simeng-li 2022-11-14 17:29:11 +08:00 committed by GitHub
parent 2168936b9c
commit 9118b59288
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 114 additions and 122 deletions

View file

@ -10,6 +10,7 @@ import initI18n from './i18n/init';
import Callback from './pages/Callback';
import Consent from './pages/Consent';
import Continue from './pages/Continue';
import ContinueWithEmailOrPhone from './pages/Continue/EmailOrPhone';
import ErrorPage from './pages/ErrorPage';
import ForgotPassword from './pages/ForgotPassword';
import Passcode from './pages/Passcode';
@ -93,6 +94,7 @@ const App = () => {
<Route path="/forgot-password/:method" element={<ForgotPassword />} />
{/* Continue set up missing profile */}
<Route path="/continue/email-or-sms/:method" element={<ContinueWithEmailOrPhone />} />
<Route path="/continue/:method" element={<Continue />} />
{/* Social sign-in pages */}

View file

@ -10,12 +10,12 @@ type Props = {
const PasswordlessSwitch = ({ target, className }: Props) => {
const { t } = useTranslation();
const { pathname } = useLocation();
const { pathname, search } = useLocation();
const targetPathname = pathname.replace(target === 'email' ? 'sms' : 'email', target);
const targetPathname = pathname.split('/').slice(0, -1).join('/') + `/${target}`;
return (
<TextLink replace className={className} to={targetPathname}>
<TextLink replace className={className} to={{ pathname: targetPathname, search }}>
{t('action.switch_to', {
method: t(`description.${target === 'email' ? 'email' : 'phone_number'}`),
})}

View file

@ -47,7 +47,7 @@ const useRequiredProfileErrorHandler = (replace?: boolean) => {
'user.require_email_or_sms': () => {
navigate(
{
pathname: `/${UserFlow.continue}/email`,
pathname: `/${UserFlow.continue}/email-or-sms/email`,
search: location.search,
},
{ replace }

View file

@ -0,0 +1,48 @@
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import renderWithPageContext from '@/__mocks__/RenderWithPageContext';
import SettingsProvider from '@/__mocks__/RenderWithPageContext/SettingsProvider';
import EmailOrPhone from '.';
jest.mock('i18next', () => ({
language: 'en',
}));
describe('EmailOrPhone', () => {
it('render set phone with email alterations', () => {
const { queryByText, container } = renderWithPageContext(
<SettingsProvider>
<MemoryRouter initialEntries={['/continue/email-or-sms/sms']}>
<Routes>
<Route path="/continue/email-or-sms/:method" element={<EmailOrPhone />} />
</Routes>
</MemoryRouter>
</SettingsProvider>
);
expect(queryByText('description.link_email_or_phone')).not.toBeNull();
expect(queryByText('description.link_email_or_phone_description')).not.toBeNull();
expect(container.querySelector('input[name="phone"]')).not.toBeNull();
expect(queryByText('action.continue')).not.toBeNull();
expect(queryByText('action.switch_to')).not.toBeNull();
});
it('render set email with phone alterations', () => {
const { queryByText, container } = renderWithPageContext(
<SettingsProvider>
<MemoryRouter initialEntries={['/continue/email-or-sms/email']}>
<Routes>
<Route path="/continue/email-or-sms/:method" element={<EmailOrPhone />} />
</Routes>
</MemoryRouter>
</SettingsProvider>
);
expect(queryByText('description.link_email_or_phone')).not.toBeNull();
expect(queryByText('description.link_email_or_phone_description')).not.toBeNull();
expect(container.querySelector('input[name="email"]')).not.toBeNull();
expect(queryByText('action.continue')).not.toBeNull();
expect(queryByText('action.switch_to')).not.toBeNull();
});
});

View file

@ -0,0 +1,41 @@
import { SignInIdentifier } from '@logto/schemas';
import { useParams } from 'react-router-dom';
import SecondaryPageWrapper from '@/components/SecondaryPageWrapper';
import { EmailContinue } from '@/containers/EmailForm';
import { SmsContinue } from '@/containers/PhoneForm';
import ErrorPage from '@/pages/ErrorPage';
type Parameters = {
method?: string;
};
const EmailOrPhone = () => {
const { method = '' } = useParams<Parameters>();
if (method === SignInIdentifier.Email) {
return (
<SecondaryPageWrapper
title="description.link_email_or_phone"
description="description.link_email_or_phone_description"
>
<EmailContinue autoFocus hasSwitch />
</SecondaryPageWrapper>
);
}
if (method === SignInIdentifier.Sms) {
return (
<SecondaryPageWrapper
title="description.link_email_or_phone"
description="description.link_email_or_phone_description"
>
<SmsContinue autoFocus hasSwitch />
</SecondaryPageWrapper>
);
}
return <ErrorPage />;
};
export default EmailOrPhone;

View file

@ -32,26 +32,4 @@ describe('SetEmail', () => {
expect(container.querySelector('input[name="email"]')).not.toBeNull();
expect(queryByText('action.continue')).not.toBeNull();
});
it('render set email with phone alterations', () => {
const { queryByText, container } = renderWithPageContext(
<SettingsProvider
settings={{
...mockSignInExperienceSettings,
signUp: {
...mockSignInExperienceSettings.signUp,
methods: [SignInIdentifier.Email, SignInIdentifier.Sms],
},
}}
>
<SetEmail />
</SettingsProvider>
);
expect(queryByText('description.link_email_or_phone')).not.toBeNull();
expect(queryByText('description.link_email_or_phone_description')).not.toBeNull();
expect(container.querySelector('input[name="email"]')).not.toBeNull();
expect(queryByText('action.continue')).not.toBeNull();
expect(queryByText('action.switch_to')).not.toBeNull();
});
});

View file

@ -1,31 +1,13 @@
import { SignInIdentifier } from '@logto/schemas';
import SecondaryPageWrapper from '@/components/SecondaryPageWrapper';
import { EmailContinue } from '@/containers/EmailForm';
import { useSieMethods } from '@/hooks/use-sie';
import ErrorPage from '@/pages/ErrorPage';
const SetEmail = () => {
const { signUpMethods } = useSieMethods();
if (!signUpMethods.includes(SignInIdentifier.Email)) {
return <ErrorPage />;
}
const phoneSignUpAlteration = signUpMethods.includes(SignInIdentifier.Sms);
return (
<SecondaryPageWrapper
title={phoneSignUpAlteration ? 'description.link_email_or_phone' : 'description.link_email'}
description={
phoneSignUpAlteration
? 'description.link_email_or_phone_description'
: 'description.link_email_description'
}
>
<EmailContinue autoFocus hasSwitch={phoneSignUpAlteration} />
</SecondaryPageWrapper>
);
};
const SetEmail = () => (
<SecondaryPageWrapper
title="description.link_email"
description="description.link_email_description"
>
<EmailContinue autoFocus />
</SecondaryPageWrapper>
);
export default SetEmail;

View file

@ -1,20 +1,11 @@
import SecondaryPageWrapper from '@/components/SecondaryPageWrapper';
import SetPasswordForm from '@/containers/SetPassword';
import { useSieMethods } from '@/hooks/use-sie';
import ErrorPage from '@/pages/ErrorPage';
import useSetPassword from './use-set-password';
const SetPassword = () => {
const { setPassword } = useSetPassword();
const { signUpSettings } = useSieMethods();
// Password not enabled for sign-up identifiers
if (!signUpSettings.password) {
return <ErrorPage />;
}
return (
<SecondaryPageWrapper title="description.set_password">
<SetPasswordForm autoFocus onSubmit={setPassword} />

View file

@ -36,26 +36,4 @@ describe('SetPhone', () => {
expect(container.querySelector('input[name="phone"]')).not.toBeNull();
expect(queryByText('action.continue')).not.toBeNull();
});
it('render set phone with email alterations', () => {
const { queryByText, container } = renderWithPageContext(
<SettingsProvider
settings={{
...mockSignInExperienceSettings,
signUp: {
...mockSignInExperienceSettings.signUp,
methods: [SignInIdentifier.Email, SignInIdentifier.Sms],
},
}}
>
<SetPhone />
</SettingsProvider>
);
expect(queryByText('description.link_email_or_phone')).not.toBeNull();
expect(queryByText('description.link_email_or_phone_description')).not.toBeNull();
expect(container.querySelector('input[name="phone"]')).not.toBeNull();
expect(queryByText('action.continue')).not.toBeNull();
expect(queryByText('action.switch_to')).not.toBeNull();
});
});

View file

@ -1,29 +1,13 @@
import { SignInIdentifier } from '@logto/schemas';
import SecondaryPageWrapper from '@/components/SecondaryPageWrapper';
import { SmsContinue } from '@/containers/PhoneForm';
import { useSieMethods } from '@/hooks/use-sie';
import ErrorPage from '@/pages/ErrorPage';
const SetPhone = () => {
const { signUpMethods } = useSieMethods();
if (!signUpMethods.includes(SignInIdentifier.Sms)) {
return <ErrorPage />;
}
const emailSignUpAlteration = signUpMethods.includes(SignInIdentifier.Email);
return (
<SecondaryPageWrapper
title={emailSignUpAlteration ? 'description.link_email_or_phone' : 'description.link_phone'}
description={
emailSignUpAlteration
? 'description.link_email_or_phone_description'
: 'description.link_phone_description'
}
title="description.link_phone"
description="description.link_phone_description"
>
<SmsContinue autoFocus hasSwitch={emailSignUpAlteration} />
<SmsContinue autoFocus />
</SecondaryPageWrapper>
);
};

View file

@ -1,25 +1,13 @@
import { SignInIdentifier } from '@logto/schemas';
import SecondaryPageWrapper from '@/components/SecondaryPageWrapper';
import { SetUsername as SetUsernameForm } from '@/containers/UsernameForm';
import { useSieMethods } from '@/hooks/use-sie';
import ErrorPage from '@/pages/ErrorPage';
const SetUsername = () => {
const { signUpMethods } = useSieMethods();
if (!signUpMethods.includes(SignInIdentifier.Username)) {
return <ErrorPage />;
}
return (
<SecondaryPageWrapper
title="description.enter_username"
description="description.enter_username_description"
>
<SetUsernameForm />
</SecondaryPageWrapper>
);
};
const SetUsername = () => (
<SecondaryPageWrapper
title="description.enter_username"
description="description.enter_username_description"
>
<SetUsernameForm />
</SecondaryPageWrapper>
);
export default SetUsername;