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:
parent
2168936b9c
commit
9118b59288
11 changed files with 114 additions and 122 deletions
|
@ -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 */}
|
||||
|
|
|
@ -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'}`),
|
||||
})}
|
||||
|
|
|
@ -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 }
|
||||
|
|
48
packages/ui/src/pages/Continue/EmailOrPhone/index.test.tsx
Normal file
48
packages/ui/src/pages/Continue/EmailOrPhone/index.test.tsx
Normal 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();
|
||||
});
|
||||
});
|
41
packages/ui/src/pages/Continue/EmailOrPhone/index.tsx
Normal file
41
packages/ui/src/pages/Continue/EmailOrPhone/index.tsx
Normal 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;
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue