Skip to content

Commit

Permalink
feat: 영감탱 익스텐션 로그인
Browse files Browse the repository at this point in the history
  • Loading branch information
ddarkr committed Feb 18, 2024
1 parent 6d0e7f2 commit b592801
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
11 changes: 7 additions & 4 deletions src/components/common/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PropsWithChildren, ReactNode, useEffect, useState } from 'react';
import { css, Theme } from '@emotion/react';
import { css, Theme, useTheme } from '@emotion/react';
import { motion } from 'framer-motion';

import PortalWrapper from '~/components/common/PortalWrapper';
Expand All @@ -10,13 +10,16 @@ import { dimBackdropCss } from './styles';
export interface DialogProps {
isShowing?: boolean;
actionButtons: ReactNode;
dialogWidth?: number;
}

export default function Dialog({
isShowing,
children,
actionButtons,
dialogWidth,
}: PropsWithChildren<DialogProps>) {
const theme = useTheme();
const [isSSR, setIsSSR] = useState(true);

useEffect(() => {
Expand All @@ -34,7 +37,7 @@ export default function Dialog({
animate="animate"
exit="exit"
>
<motion.div css={dialogCss} variants={defaultFadeInUpVariants}>
<motion.div css={dialogCss(theme, dialogWidth)} variants={defaultFadeInUpVariants}>
<div css={dialogContentWrapperCss}>{children}</div>
<div css={dialogButtonWrapperCss}>{actionButtons}</div>
</motion.div>
Expand All @@ -54,14 +57,14 @@ const dimBackdropLayoutCss = (theme: Theme) => css`
${dimBackdropCss(theme)}
`;

const dialogCss = (theme: Theme) => css`
const dialogCss = (theme: Theme, width = 311) => css`
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
width: 311px;
width: ${width}px;
min-height: 200px;
background-color: ${theme.color.background};
Expand Down
5 changes: 5 additions & 0 deletions src/constants/localStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ export const localStorageUserTokenKeys = {
accessToken: 'ygtlsat',
refreshToken: 'ygtrfhtk',
} as const;

export const localStorageExtensionKeys = {
use: 'use-ygtang-extension',
refreshToken: 'ygte-refresh',
} as const;
2 changes: 1 addition & 1 deletion src/libs/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CustomException from '~/exceptions/CustomException';
import { errorMessage } from '~/exceptions/messages';
import { ApiErrorScheme } from '~/exceptions/type';

const DEVELOPMENT_API_URL = 'https://api.ygtang.xyz/api';
const DEVELOPMENT_API_URL = 'https://ygtang.kr/api'; // TODO: 개발 서버 사망에 따른 개발 버전에서도 프로덕션 사용
const PRODUCTION_API_URL = 'https://ygtang.kr/api';

export const instance = axios.create({
Expand Down
74 changes: 73 additions & 1 deletion src/pages/login/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { FormEvent, useEffect, useState } from 'react';
import { css, Theme } from '@emotion/react';

import { CTAButton, GhostButton } from '~/components/common/Button';
import { CTAButton, FilledButton, GhostButton } from '~/components/common/Button';
import Dialog from '~/components/common/Dialog';
import SEO from '~/components/common/SEO';
import TextField from '~/components/common/TextField';
import { localStorageExtensionKeys } from '~/constants/localStorage';
import useMemberLoginMutation from '~/hooks/api/member/useMemberLoginMutation';
import useReissueMutation from '~/hooks/api/reissue/useReissueMutation';
import useDidUpdate from '~/hooks/common/useDidUpdate';
import useInput from '~/hooks/common/useInput';
import useInternalRouter from '~/hooks/common/useInternalRouter';
Expand All @@ -19,6 +22,7 @@ export default function Login() {
const email = useInput({});
const password = useInput({});
const [isPending, setIsPending] = useState(false);
const [canExtensionLogin, setCanExtensionLogin] = useState(false);
const [emailError, setEmailError] = useState('');
const [passwordError, setPasswordError] = useState('');
const { userLogin } = useUser();
Expand All @@ -30,6 +34,27 @@ export default function Login() {
data: loginMutationData,
error: loginMutationError,
} = useMemberLoginMutation();
const { mutate: reissueMutate } = useReissueMutation({
onSuccess: ({ data }) => {
userLogin({
accessToken: data.accessToken,
refreshToken: data.refreshToken,
});
setIsPending(false);
recordEvent({ action: 'Login', value: '로그인 화면에서 익스텐션 계정으로 로그인' });

if (getRedirect()) {
goRedirect();
} else {
push('/');
}
},
onError: () => {
fireToast({ content: '익스텐션 계정으로 로그인하는데 실패했습니다.' });
setCanExtensionLogin(false);
setIsPending(false);
},
});

const handleFormSubmitEvent = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
Expand All @@ -46,6 +71,14 @@ export default function Login() {
});
};

const handleExtensionLogin = () => {
setIsPending(true);
const token = localStorage.getItem(localStorageExtensionKeys.refreshToken);
if (token) {
reissueMutate({ refreshToken: token });
}
};

useDidUpdate(() => {
if (!validator({ type: 'email', value: email.value })) {
setEmailError('올바른 이메일을 입력해주세요.');
Expand Down Expand Up @@ -86,6 +119,16 @@ export default function Login() {
}
}, [fireToast, loginMutationError]);

useEffect(() => {
if (
localStorage &&
localStorage.getItem(localStorageExtensionKeys.use) &&
localStorage.getItem(localStorageExtensionKeys.refreshToken)
) {
setCanExtensionLogin(true);
}
}, []);

return (
<>
<SEO title="로그인" />
Expand Down Expand Up @@ -127,6 +170,30 @@ export default function Login() {
빠르게 가입하기
</GhostButton>
</div>
<Dialog
isShowing={canExtensionLogin}
dialogWidth={300}
actionButtons={
<>
<FilledButton
colorType="light"
onClick={() => setCanExtensionLogin(false)}
disabled={isPending}
>
다른 계정
</FilledButton>
<div css={dialogLongButtonCss}>
<FilledButton colorType="dark" onClick={handleExtensionLogin} disabled={isPending}>
익스텐션 계정
</FilledButton>
</div>
</>
}
>
영감탱 익스텐션에 로그인되어 있습니다.
<br />
익스텐션 계정으로 로그인할까요?
</Dialog>
</article>
</>
);
Expand Down Expand Up @@ -166,3 +233,8 @@ const signUpTextWrapperCss = (theme: Theme) => css`
font-size: 10px;
line-height: 150%;
`;

const dialogLongButtonCss = css`
width: 160px;
flex-shrink: 0;
`;

0 comments on commit b592801

Please sign in to comment.