mirror of
https://github.com/logto-io/logto.git
synced 2025-03-10 22:22:45 -05:00
refactor(ui): extract useBindSocial hook (#667)
extract useBindSocial hook
This commit is contained in:
parent
12cf518c88
commit
ce4d6daad2
4 changed files with 76 additions and 46 deletions
|
@ -21,13 +21,13 @@ jest.mock('@/apis/social', () => ({
|
|||
|
||||
describe('SocialCreateAccount', () => {
|
||||
it('should match snapshot', () => {
|
||||
const { queryByText } = render(<SocialCreateAccount connector="github" />);
|
||||
const { queryByText } = render(<SocialCreateAccount connectorId="github" />);
|
||||
expect(queryByText('description.social_create_account')).not.toBeNull();
|
||||
expect(queryByText('description.social_bind_account')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should redirect to sign in page when click sign-in button', () => {
|
||||
const { getByText } = render(<SocialCreateAccount connector="github" />);
|
||||
const { getByText } = render(<SocialCreateAccount connectorId="github" />);
|
||||
|
||||
const signInButton = getByText('action.sign_in');
|
||||
fireEvent.click(signInButton);
|
||||
|
@ -35,7 +35,7 @@ describe('SocialCreateAccount', () => {
|
|||
});
|
||||
|
||||
it('should call registerWithSocial when click create button', async () => {
|
||||
const { getByText } = renderWithPageContext(<SocialCreateAccount connector="github" />);
|
||||
const { getByText } = renderWithPageContext(<SocialCreateAccount connectorId="github" />);
|
||||
const createButton = getByText('action.create');
|
||||
|
||||
await waitFor(() => {
|
||||
|
@ -46,7 +46,7 @@ describe('SocialCreateAccount', () => {
|
|||
});
|
||||
|
||||
it('should render bindUser Button when relatedUserInfo found', async () => {
|
||||
const { getByText } = renderWithPageContext(<SocialCreateAccount connector="github" />);
|
||||
const { getByText } = renderWithPageContext(<SocialCreateAccount connectorId="github" />);
|
||||
const bindButton = getByText('action.bind');
|
||||
await waitFor(() => {
|
||||
fireEvent.click(bindButton);
|
||||
|
|
|
@ -1,69 +1,49 @@
|
|||
import { Optional } from '@silverhand/essentials';
|
||||
import classNames from 'classnames';
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { registerWithSocial, bindSocialRelatedUser } from '@/apis/social';
|
||||
import Button from '@/components/Button';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useBindSocial from '@/hooks/use-bind-social';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
connector: string;
|
||||
connectorId: string;
|
||||
};
|
||||
|
||||
type LocationState = {
|
||||
relatedUser?: string;
|
||||
};
|
||||
|
||||
const SocialCreateAccount = ({ connector, className }: Props) => {
|
||||
const SocialCreateAccount = ({ connectorId, className }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const state = useLocation().state as Optional<LocationState>;
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'main_flow' });
|
||||
|
||||
const { result: registerResult, run: asyncRegisterWithSocial } = useApi(registerWithSocial);
|
||||
const { result: bindUserResult, run: asyncBindSocialRelatedUser } = useApi(bindSocialRelatedUser);
|
||||
|
||||
const createAccountHandler = useCallback(() => {
|
||||
void asyncRegisterWithSocial(connector);
|
||||
}, [asyncRegisterWithSocial, connector]);
|
||||
|
||||
const bindRelatedUserHandler = useCallback(() => {
|
||||
void asyncBindSocialRelatedUser(connector);
|
||||
}, [asyncBindSocialRelatedUser, connector]);
|
||||
const { relatedUser, registerWithSocial, bindSocialRelatedUser } = useBindSocial();
|
||||
|
||||
const signInHandler = useCallback(() => {
|
||||
// TODO: redirect to desired sign-in page
|
||||
navigate('/sign-in/username/' + connector);
|
||||
}, [connector, navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (registerResult?.redirectTo) {
|
||||
window.location.assign(registerResult.redirectTo);
|
||||
}
|
||||
}, [registerResult]);
|
||||
|
||||
useEffect(() => {
|
||||
if (bindUserResult?.redirectTo) {
|
||||
window.location.assign(bindUserResult.redirectTo);
|
||||
}
|
||||
}, [bindUserResult]);
|
||||
navigate('/sign-in/username/' + connectorId);
|
||||
}, [connectorId, navigate]);
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.container, className)}>
|
||||
{state?.relatedUser && (
|
||||
{relatedUser && (
|
||||
<>
|
||||
<div className={styles.desc}>{t('description.social_bind_with_existing')}</div>
|
||||
<Button onClick={bindRelatedUserHandler}>
|
||||
{t('action.bind', { address: state.relatedUser })}
|
||||
<Button
|
||||
onClick={() => {
|
||||
bindSocialRelatedUser(connectorId);
|
||||
}}
|
||||
>
|
||||
{t('action.bind', { address: relatedUser })}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<div className={styles.desc}>{t('description.social_create_account')}</div>
|
||||
<Button type={state?.relatedUser ? 'secondary' : 'primary'} onClick={createAccountHandler}>
|
||||
<Button
|
||||
type={relatedUser ? 'secondary' : 'primary'}
|
||||
onClick={() => {
|
||||
registerWithSocial(connectorId);
|
||||
}}
|
||||
>
|
||||
{t('action.create')}
|
||||
</Button>
|
||||
<div className={styles.desc}>{t('description.social_bind_account')}</div>
|
||||
|
|
50
packages/ui/src/hooks/use-bind-social.ts
Normal file
50
packages/ui/src/hooks/use-bind-social.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { Optional } from '@silverhand/essentials';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { registerWithSocial, bindSocialRelatedUser } from '@/apis/social';
|
||||
import useApi from '@/hooks/use-api';
|
||||
|
||||
type LocationState = {
|
||||
relatedUser?: string;
|
||||
};
|
||||
|
||||
const useBindSocial = () => {
|
||||
const state = useLocation().state as Optional<LocationState>;
|
||||
const { result: registerResult, run: asyncRegisterWithSocial } = useApi(registerWithSocial);
|
||||
const { result: bindUserResult, run: asyncBindSocialRelatedUser } = useApi(bindSocialRelatedUser);
|
||||
|
||||
const createAccountHandler = useCallback(
|
||||
(connectorId: string) => {
|
||||
void asyncRegisterWithSocial(connectorId);
|
||||
},
|
||||
[asyncRegisterWithSocial]
|
||||
);
|
||||
|
||||
const bindRelatedUserHandler = useCallback(
|
||||
(connectorId) => {
|
||||
void asyncBindSocialRelatedUser(connectorId);
|
||||
},
|
||||
[asyncBindSocialRelatedUser]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (registerResult?.redirectTo) {
|
||||
window.location.assign(registerResult.redirectTo);
|
||||
}
|
||||
}, [registerResult]);
|
||||
|
||||
useEffect(() => {
|
||||
if (bindUserResult?.redirectTo) {
|
||||
window.location.assign(bindUserResult.redirectTo);
|
||||
}
|
||||
}, [bindUserResult]);
|
||||
|
||||
return {
|
||||
relatedUser: state?.relatedUser,
|
||||
registerWithSocial: createAccountHandler,
|
||||
bindSocialRelatedUser: bindRelatedUserHandler,
|
||||
};
|
||||
};
|
||||
|
||||
export default useBindSocial;
|
|
@ -29,7 +29,7 @@ const SocialRegister = () => {
|
|||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<NavBar title={t('description.bind_account_title')} />
|
||||
<SocialCreateAccount connector={connector} />
|
||||
<SocialCreateAccount connectorId={connector} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue