Skip to content

Commit a06823d

Browse files
committed
fix: pass state and implement email login on integration
1 parent f8ac12a commit a06823d

File tree

5 files changed

+97
-12
lines changed

5 files changed

+97
-12
lines changed

src/components/auth/AuthEmailSuccess.tsx

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as React from 'react';
2-
import styled from 'styled-components';
2+
import styled, { css } from 'styled-components';
33
import { MdCheck } from 'react-icons/md';
44
import palette from '../../lib/styles/palette';
55

6-
const AuthEmailSuccessBlock = styled.div`
6+
const AuthEmailSuccessBlock = styled.div<{ isIntegrate?: boolean }>`
77
display: flex;
88
align-items: center;
99
background: ${palette.teal1};
@@ -12,6 +12,7 @@ const AuthEmailSuccessBlock = styled.div`
1212
padding-right: 0.75rem;
1313
height: 3rem;
1414
color: ${palette.teal9};
15+
white-space: pre;
1516
.icon {
1617
font-size: 1.5rem;
1718
}
@@ -20,18 +21,58 @@ const AuthEmailSuccessBlock = styled.div`
2021
flex: 1;
2122
text-align: center;
2223
}
24+
25+
${(props) =>
26+
props.isIntegrate &&
27+
css`
28+
height: 4rem;
29+
`}
30+
`;
31+
32+
const FakeLink = styled.button`
33+
display: inline;
34+
cursor: pointer;
35+
text-decoration: underline;
36+
font-weight: 600;
37+
background: none;
38+
padding: 0;
39+
border: none;
40+
outline: none;
41+
color: ${palette.teal9};
42+
&:hover {
43+
color: ${palette.teal7};
44+
}
2345
`;
2446

2547
export interface AuthEmailSuccessProps {
2648
registered: boolean;
49+
isIntegrate?: boolean;
2750
}
2851

29-
const AuthEmailSuccess: React.FC<AuthEmailSuccessProps> = ({ registered }) => {
52+
const AuthEmailSuccess: React.FC<AuthEmailSuccessProps> = ({
53+
registered,
54+
isIntegrate,
55+
}) => {
3056
const text = registered ? '로그인' : '회원가입';
3157
return (
32-
<AuthEmailSuccessBlock>
58+
<AuthEmailSuccessBlock isIntegrate={isIntegrate}>
3359
<MdCheck className="icon" />
34-
<div className="description">{text} 링크가 이메일로 전송되었습니다.</div>
60+
<div className="description">
61+
{text} 링크가 이메일로 전송되었습니다.
62+
{isIntegrate ? (
63+
<>
64+
{'\n'}로그인 후 이 창에서{' '}
65+
<FakeLink
66+
onClick={() => {
67+
window.location.reload();
68+
}}
69+
>
70+
새로고침
71+
</FakeLink>
72+
을 해주세요.
73+
</>
74+
) : null}
75+
</div>
3576
</AuthEmailSuccessBlock>
3677
);
3778
};

src/components/auth/AuthForm.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface AuthFormProps {
7171
registered: boolean | null;
7272
currentPath: string;
7373
isIntegrate?: boolean;
74+
integrateState?: string;
7475
}
7576

7677
const AuthForm: React.FC<AuthFormProps> = ({
@@ -81,6 +82,7 @@ const AuthForm: React.FC<AuthFormProps> = ({
8182
registered,
8283
currentPath,
8384
isIntegrate,
85+
integrateState,
8486
}) => {
8587
const [email, onChangeEmail] = useInput('');
8688
const onSubmit = (email: string) => {
@@ -96,7 +98,10 @@ const AuthForm: React.FC<AuthFormProps> = ({
9698
<section>
9799
<h4>이메일로 {modeText}</h4>
98100
{registered !== null ? (
99-
<AuthEmailSuccess registered={registered} />
101+
<AuthEmailSuccess
102+
registered={registered}
103+
isIntegrate={isIntegrate}
104+
/>
100105
) : (
101106
<AuthEmailForm
102107
value={email}
@@ -112,6 +117,7 @@ const AuthForm: React.FC<AuthFormProps> = ({
112117
<AuthSocialButtonGroup
113118
currentPath={currentPath}
114119
isIntegrate={isIntegrate}
120+
integrateState={integrateState}
115121
/>
116122
</section>
117123
</div>

src/components/auth/AuthSocialButton.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface AuthSocialButtonProps {
2828
tabIndex?: number;
2929
currentPath: string;
3030
isIntegrate?: boolean;
31+
integrateState?: string;
3132
}
3233

3334
const providerMap = {
@@ -53,6 +54,7 @@ const AuthSocialButton: React.FC<AuthSocialButtonProps> = ({
5354
tabIndex,
5455
currentPath,
5556
isIntegrate,
57+
integrateState,
5658
}) => {
5759
const info = providerMap[provider];
5860
const { icon: Icon, color, border } = info;
@@ -64,7 +66,7 @@ const AuthSocialButton: React.FC<AuthSocialButtonProps> = ({
6466

6567
const redirectTo = `${host}api/v2/auth/social/redirect/${provider}?next=${currentPath}&isIntegrate=${
6668
isIntegrate ? 1 : 0
67-
}`;
69+
}${integrateState ? `&integrateState=${integrateState}` : ''}`;
6870

6971
return (
7072
<AuthSocialButtonBlock

src/components/auth/AuthSocialButtonGroup.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ const AuthSocialButtonGroupBlock = styled.div`
1111
const AuthSocialButtonGroup = ({
1212
currentPath,
1313
isIntegrate,
14+
integrateState,
1415
}: {
1516
currentPath: string;
1617
isIntegrate?: boolean;
18+
integrateState?: string;
1719
}) => {
1820
return (
1921
<AuthSocialButtonGroupBlock>
@@ -22,18 +24,21 @@ const AuthSocialButtonGroup = ({
2224
tabIndex={4}
2325
currentPath={currentPath}
2426
isIntegrate={isIntegrate}
27+
integrateState={integrateState}
2528
/>
2629
<AuthSocialButton
2730
provider="google"
2831
tabIndex={5}
2932
currentPath={currentPath}
3033
isIntegrate={isIntegrate}
34+
integrateState={integrateState}
3135
/>
3236
<AuthSocialButton
3337
provider="facebook"
3438
tabIndex={6}
3539
currentPath={currentPath}
3640
isIntegrate={isIntegrate}
41+
integrateState={integrateState}
3742
/>
3843
</AuthSocialButtonGroupBlock>
3944
);

src/components/user-integrate/UserIntegrateTemplate.tsx

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useCallback } from 'react';
22
import styled from 'styled-components';
33
import useUser from '../../lib/hooks/useUser';
44
import media from '../../lib/styles/media';
@@ -11,12 +11,36 @@ import {
1111
ACCEPT_INTEGRATION,
1212
AcceptIntegrationResponse,
1313
} from '../../lib/graphql/user';
14+
import { useLocation } from 'react-router-dom';
15+
import qs from 'qs';
16+
import { toast } from 'react-toastify';
17+
import useRequest from '../../lib/hooks/useRequest';
18+
import { SendAuthEmailResponse, sendAuthEmail } from '../../lib/api/auth';
1419

1520
function UserIntegrateTemplate() {
1621
const user = useUser();
22+
const location = useLocation();
23+
const query = qs.parse(location.search, { ignoreQueryPrefix: true });
24+
const integrateState = query.state ?? '';
25+
const [_sendAuthEmail, loading, data, , resetSendAuthEmail] =
26+
useRequest<SendAuthEmailResponse>(sendAuthEmail);
27+
1728
const [acceptIntegration] =
1829
useMutation<AcceptIntegrationResponse>(ACCEPT_INTEGRATION);
1930

31+
const onSendAuthEmail = useCallback(
32+
async (email: string) => {
33+
if (!validateEmail(email)) {
34+
toast.error('잘못된 이메일 형식입니다.');
35+
return;
36+
}
37+
_sendAuthEmail(email);
38+
},
39+
[_sendAuthEmail],
40+
);
41+
42+
const registered = data && data.registered;
43+
2044
return (
2145
<Block>
2246
<Content>
@@ -45,7 +69,7 @@ function UserIntegrateTemplate() {
4569
onClick={async () => {
4670
const result = await acceptIntegration();
4771
if (!result.data) return;
48-
window.location.href = `https://api-dev.codenary.co.kr/contents/velog/callback?code=${result.data.acceptIntegration}`;
72+
window.location.href = `https://api-dev.codenary.co.kr/contents/velog/callback?code=${result.data.acceptIntegration}&state=${integrateState}`;
4973
}}
5074
>
5175
승인
@@ -56,11 +80,12 @@ function UserIntegrateTemplate() {
5680
<AuthForm
5781
mode="LOGIN"
5882
onToggleMode={() => {}}
59-
onSendAuthEmail={() => {}}
60-
loading={false}
61-
registered={null}
83+
onSendAuthEmail={onSendAuthEmail}
84+
loading={loading}
85+
registered={registered}
6286
currentPath="/user-integrate"
6387
isIntegrate
88+
integrateState={integrateState}
6489
/>
6590
)}
6691
</Content>
@@ -128,3 +153,9 @@ const DataRow = styled.div`
128153
`;
129154

130155
export default UserIntegrateTemplate;
156+
157+
function validateEmail(email: string) {
158+
const re =
159+
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
160+
return re.test(String(email).toLowerCase());
161+
}

0 commit comments

Comments
 (0)