-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FE] 카카오 로그인 기능 추가 #833
[FE] 카카오 로그인 기능 추가 #833
Changes from 14 commits
00969c8
eb8cca3
635d9bc
c495266
a0a0cfd
f14a9a1
bf80262
b727e1f
25b4690
b7bd3b3
558acfd
27adf0c
da4f5dc
6c6ab93
4587836
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,6 +63,19 @@ export const requestGet = async <T>({ | |
return data; | ||
}; | ||
|
||
export const requestGetWithoutResponse = async ({ | ||
headers = {}, | ||
errorHandlingStrategy, | ||
...args | ||
}: WithErrorHandlingStrategy<RequestMethodProps>) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 신경써서 구현해줘서 고맙습니다. 더 편리한 방법을 찾고 싶은데 마땅히 떠오르는게 없네요 ㅜㅜ.... |
||
await request({ | ||
...args, | ||
method: 'GET', | ||
headers, | ||
errorHandlingStrategy, | ||
}); | ||
}; | ||
|
||
export const requestPatch = ({headers = {}, ...args}: RequestMethodProps) => { | ||
return request({method: 'PATCH', headers, ...args}); | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import {BASE_URL} from '@apis/baseUrl'; | ||
import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; | ||
import {requestPostWithoutResponse} from '@apis/fetcher'; | ||
import {requestGet, requestGetWithoutResponse, requestPostWithoutResponse} from '@apis/fetcher'; | ||
import {WithEventId} from '@apis/withId.type'; | ||
|
||
export const requestPostAuthentication = async ({eventId}: WithEventId) => { | ||
|
@@ -23,3 +23,24 @@ export const requestPostToken = async ({eventId, password}: WithEventId<RequestP | |
}, | ||
}); | ||
}; | ||
|
||
export const requestKakaoClientId = async () => { | ||
return await requestGet<{clientId: string}>({ | ||
baseUrl: BASE_URL.HD, | ||
endpoint: '/api/kakao-client-id', | ||
}); | ||
}; | ||
|
||
export const requestGetKakaoLogin = async (code: string) => { | ||
const redirectUri = | ||
process.env.NODE_ENV === 'development' | ||
? 'http://localhost:3000' + process.env.KAKAO_REDIRECT_URI | ||
: 'https://haengdong.pro' + process.env.KAKAO_REDIRECT_URI; | ||
|
||
await requestGetWithoutResponse({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GET인데 바디가없는 GET도 있었군요!.. 쿠키만 세팅해주고 끝나기 때문인가보네요. 새로 알아갑니다~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 근데 그럼 또 궁금한게 바디없는 POST로 만들면 안됐던걸까요!? |
||
baseUrl: BASE_URL.HD, | ||
endpoint: `/api/login/kakao?code=${code}&redirect_uri=${redirectUri}`, | ||
}); | ||
|
||
return null; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -81,7 +81,9 @@ export type ColorKeys = | |
| 'errorContainer' | ||
| 'onErrorContainer' | ||
| 'warn' | ||
| 'complete'; | ||
| 'complete' | ||
| 'kakao' | ||
| 'onKakao'; | ||
export type ColorTokens = Record<ColorKeys, Color>; | ||
|
||
// TODO: (@soha) 대괄호 사용에 대해 논의 | ||
|
@@ -106,6 +108,9 @@ export const COLORS: ColorTokens = { | |
onErrorContainer: PRIMITIVE_COLORS.pink[300], | ||
warn: PRIMITIVE_COLORS.yellow[400], | ||
complete: PRIMITIVE_COLORS.green[300], | ||
|
||
kakao: '#FEE500', | ||
onKakao: '#181600', | ||
Comment on lines
+112
to
+113
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 조금 번거로울 수 있긴 하지만, 해당 컬러들도 위에 PRIMITIVE_COLORS 처럼 객체로 관리해서 넣어주는게 통일성 있고 좋을 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오매. 이전에 토다리가 저와 약간 반대 의견을 내주셔서 수정했던 거군요! 호홍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 소하의 의견도 좋은 아이디어네요~ BRAND_COLORS 와 같은 것을 만들어서 넣어줘도 되겠네요~ |
||
}; | ||
|
||
export const PRIMARY_COLORS = PRIMITIVE_COLORS.purple; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import {useQuery} from '@tanstack/react-query'; | ||
|
||
import {requestKakaoClientId} from '@apis/request/auth'; | ||
|
||
import QUERY_KEYS from '@constants/queryKeys'; | ||
|
||
const useRequestGetKakaoClientId = () => { | ||
const {refetch, ...rest} = useQuery({ | ||
queryKey: [QUERY_KEYS.kakaoClientId], | ||
queryFn: requestKakaoClientId, | ||
enabled: false, | ||
}); | ||
|
||
return { | ||
requestGetClientId: refetch, | ||
...rest, | ||
}; | ||
}; | ||
|
||
export default useRequestGetKakaoClientId; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import {useQuery} from '@tanstack/react-query'; | ||
|
||
import {requestGetKakaoLogin} from '@apis/request/auth'; | ||
|
||
import QUERY_KEYS from '@constants/queryKeys'; | ||
|
||
const useRequestGetKakaoLogin = () => { | ||
const code = new URLSearchParams(location.search).get('code'); | ||
|
||
const {refetch, ...rest} = useQuery({ | ||
queryKey: [QUERY_KEYS.kakaoLogin, code], | ||
queryFn: () => requestGetKakaoLogin(code ?? ''), | ||
enabled: false, | ||
}); | ||
|
||
return { | ||
requestGetKakaoLogin: refetch, | ||
...rest, | ||
}; | ||
}; | ||
|
||
export default useRequestGetKakaoLogin; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import {useEffect} from 'react'; | ||
import {useLocation, useNavigate} from 'react-router-dom'; | ||
|
||
import {useAuthStore} from '@store/authStore'; | ||
|
||
import {ROUTER_URLS} from '@constants/routerUrls'; | ||
|
||
import useRequestGetKakaoClientId from './queries/auth/useRequestGetKakaoClientId'; | ||
import useAmplitude from './useAmplitude'; | ||
import useRequestGetKakaoLogin from './queries/auth/useRequestGetKakaoLogin'; | ||
|
||
const useLoginPage = () => { | ||
const navigate = useNavigate(); | ||
const location = useLocation(); | ||
const {trackStartCreateEvent} = useAmplitude(); | ||
const {updateAuth} = useAuthStore(); | ||
const {requestGetKakaoLogin} = useRequestGetKakaoLogin(); | ||
|
||
const {requestGetClientId} = useRequestGetKakaoClientId(); | ||
|
||
const goKakaoLogin = async () => { | ||
const queryResult = await requestGetClientId(); | ||
const clientId = queryResult.data?.clientId; | ||
const redirectUri = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. auth.ts에서도 동일하게 사용하던데 하나의 constants 파일에서 관리하는 건 어떤가용? |
||
process.env.NODE_ENV === 'development' | ||
? 'http://localhost:3000' + process.env.KAKAO_REDIRECT_URI | ||
: 'https://haengdong.pro' + process.env.KAKAO_REDIRECT_URI; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저희 app.haengdong.pro도 있긴한데, 그냥 haengdong.pro로 리다이렉션해도 괜찮겠죠? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이게 개발 환경에서 테스트할 때는 localhost:3000이라서 이렇게 해뒀어요. cypress 테스트를 할 때도 localhost:3000으로 열리니깐 문제 없다고 생각했습니다! prod는 고민이 되네요... 근데 크게 무리는 없을 것 같아요 |
||
|
||
const link = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 얘도 마찬가지로 나중에 관리할 것을 생각해서 constnats 파일에 따로 분리해두는 것도 좋을 것 같아용 |
||
window.location.href = link; | ||
}; | ||
|
||
const goNonLoginCreateEvent = () => { | ||
trackStartCreateEvent({login: false}); | ||
navigate(ROUTER_URLS.createEvent); | ||
}; | ||
|
||
useEffect(() => { | ||
if (location.search === '') return; | ||
|
||
const code = new URLSearchParams(location.search).get('code'); | ||
|
||
const kakaoLogin = async () => { | ||
if (code) { | ||
await requestGetKakaoLogin(); | ||
updateAuth(true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 비회원 관리자와 회원 관리자의 인증여부를 하나의 auth 상태로 관리해도 부작용이 없나요? |
||
|
||
// 추후에 업데이트 하는 로직 필요 | ||
trackStartCreateEvent({login: true}); | ||
navigate(ROUTER_URLS.createEvent); | ||
} | ||
}; | ||
|
||
kakaoLogin(); | ||
}, [location.search]); | ||
|
||
return {goKakaoLogin, goNonLoginCreateEvent}; | ||
}; | ||
|
||
export default useLoginPage; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,10 @@ export const authHandler = [ | |
return new HttpResponse(null, {status: 200}); | ||
}), | ||
|
||
http.get(`${MOCK_API_PREFIX}/api/login/kakao`, () => { | ||
return new HttpResponse(null, {status: 200}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
}), | ||
|
||
// POST /api/eventId/login (requestPostToken) | ||
http.post<{eventId: string}, {password: string}>( | ||
`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/login`, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import {css} from '@emotion/react'; | ||
|
||
import {Theme} from '@components/Design/theme/theme.type'; | ||
|
||
export const hrStyle = (theme: Theme) => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hr이라는 태그가 있는걸 처음 알았네요 🥹 새로운걸 배웠습니당 |
||
css({ | ||
width: '100%', | ||
height: 1, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 근데 height에 단위없이 1만 쓰면 어떻게 되나요? 그냥 px붙인 걸로 스타일계산이 되나요? |
||
|
||
backgroundColor: theme.colors.tertiary, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import Image from '@components/Design/components/Image/Image'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 혹시 이 페이지만 페이지 이름.tsx가 아니라 index.tsx인 이유가 있나요? |
||
|
||
import useLoginPage from '@hooks/useLoginPage'; | ||
|
||
import {Button, Flex, FunnelLayout, Icon, MainLayout, Text, TopNav, useTheme} from '@components/Design'; | ||
|
||
import getImageUrl from '@utils/getImageUrl'; | ||
|
||
import {hrStyle} from './LoginPage.style'; | ||
|
||
const LOGIN_COMMENT = `로그인을 하면 계좌번호를 저장하고\n이전 행사들을 쉽게 볼 수 있어요.`; | ||
|
||
const LoginPage = () => { | ||
const {theme} = useTheme(); | ||
|
||
const {goKakaoLogin, goNonLoginCreateEvent} = useLoginPage(); | ||
|
||
return ( | ||
<MainLayout backgroundColor="white"> | ||
<TopNav> | ||
<TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> | ||
</TopNav> | ||
<FunnelLayout> | ||
<Flex flexDirection="column" justifyContent="spaceBetween" height="100%"> | ||
<Flex flexDirection="column" justifyContent="center" alignItems="center" gap="1rem" margin="0 0 6rem 0"> | ||
<Image src={getImageUrl('heundeut', 'webp')} fallbackSrc={getImageUrl('heundeut', 'png')} width={109} /> | ||
<Text size="bodyBold" css={{whiteSpace: 'pre-line', textAlign: 'center'}}> | ||
{LOGIN_COMMENT} | ||
</Text> | ||
</Flex> | ||
<Flex flexDirection="column" gap="1rem" width="100%" padding="0 2rem" paddingInline="auto"> | ||
<Button variants="kakao" size="large" onClick={goKakaoLogin}> | ||
<Flex alignItems="center" gap="0.625rem"> | ||
<Icon iconType="kakao" /> | ||
카카오 로그인 | ||
</Flex> | ||
</Button> | ||
<hr css={hrStyle(theme)} /> | ||
<Button variants="secondary" size="large" onClick={goNonLoginCreateEvent}> | ||
비회원으로 진행하기 | ||
</Button> | ||
</Flex> | ||
</Flex> | ||
</FunnelLayout> | ||
</MainLayout> | ||
); | ||
}; | ||
|
||
export default LoginPage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오~ 잊지 않고 추가! 멋져용