0
Fork 0
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:
simeng-li 2022-04-26 17:31:00 +08:00 committed by GitHub
parent 12cf518c88
commit ce4d6daad2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 46 deletions

View file

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

View file

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

View 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;

View file

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