Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/api/login/oauth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Provider } from '@/types/login';
import client from '../client';

export const getOauthAccessToken = async (
provider: Provider,
code: string,
state: string
) => {
const response = await client.post(`/api/v1/auth/token/${provider}`, {
code: code,
state: state
});
const { accessToken } = response.data;
return accessToken;
};
3 changes: 2 additions & 1 deletion src/api/login/user.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { RegisterDataType } from '@/types/user';
import client, { authClient } from '../client';
import { getRefreshToken, setTokens } from '@/utils/storage';
import { Provider } from '@/types/login';

// 로그인
export const login = async (loginType: string, accessToken: string) => {
export const login = async (loginType: Provider, accessToken: string) => {
return await client.post(`/api/v1/auth/login/${loginType}`, {
accessToken: accessToken
});
Expand Down
32 changes: 25 additions & 7 deletions src/app/login/auth/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
'use client';

import { getOauthAccessToken } from '@/api/login/oauth';
import { login } from '@/api/login/user';
import Loader from '@/components/common/Loader';
import { signupState } from '@/recoil/signupStore';
import { clearLetterUrl, setOnboarding, setTokens } from '@/utils/storage';
import { Provider } from '@/types/login';
import {
clearLetterUrl,
setOnboarding,
setRecentLogin,
setTokens
} from '@/utils/storage';
import axios from 'axios';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
Expand All @@ -13,12 +20,10 @@ import styled from 'styled-components';
const Auth = () => {
const [registerToken, setRegisterToken] = useRecoilState(signupState);
const router = useRouter();
const REST_API_KEY = process.env.NEXT_PUBLIC_REST_API_KEY;
const [absoluteUrl, setAbsoluteUrl] = useState('');
const [storeUrl, setstoreUrl] = useState('');
const [type, setType] = useState('');
const [oauthAccessToken, setOauthAccessToken] = useState('');
const [provider, setProvider] = useState('');

useEffect(() => {
if (typeof window !== 'undefined') {
Expand All @@ -39,6 +44,7 @@ const Auth = () => {
const AUTHORIZATION_CODE = new URL(window.location.href).searchParams.get(
'code'
);
const STATE = new URL(window.location.href).searchParams.get('state');

const TYPE = new URL(window.location.href).searchParams.get('type');

Expand All @@ -50,13 +56,12 @@ const Auth = () => {
//type에 따라 다른 토큰 url 지정
switch (TYPE) {
case 'kakao':
setProvider('KAKAO');
try {
const response = await axios.post(
'https://kauth.kakao.com/oauth/token',
new URLSearchParams({
grant_type: 'authorization_code',
client_id: REST_API_KEY,
client_id: process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY,
redirect_uri: absoluteUrl,
code: AUTHORIZATION_CODE
}),
Expand All @@ -73,7 +78,6 @@ const Auth = () => {

break;
case 'google':
setProvider('GOOGLE');
try {
const body = new URLSearchParams({
grant_type: 'authorization_code',
Expand All @@ -100,6 +104,18 @@ const Auth = () => {
}
break;
case 'naver':
try {
const response = await getOauthAccessToken(
'NAVER' as Provider,
AUTHORIZATION_CODE,
STATE
);
setOauthAccessToken(response);
} catch (error) {
console.error('Unsupported OAuth type:', type);
clearLetterUrl();
return;
}
break;
default:
console.error('Unknown OAuth type:', TYPE);
Expand All @@ -112,12 +128,14 @@ const Auth = () => {
useEffect(() => {
try {
if (oauthAccessToken) {
login(provider, oauthAccessToken)
login(type?.toUpperCase() as Provider, oauthAccessToken)
.then((res) => {
console.log('accessToken', res.data.accessToken);
setTokens(res.data.accessToken, res.data.refreshToken);
/* 온보딩 여부 저장 */
setOnboarding(res.data.isProcessedOnboarding);
/* 최근 로그인 정보 저장 */
setRecentLogin(type);
if (storeUrl) {
router.push(`/verify/letter?url=${storeUrl}`);
clearLetterUrl();
Expand Down
74 changes: 22 additions & 52 deletions src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,17 @@
'use client';

import SocialKakao from '@/components/signup/SocialKakao';
import SocialGoogle from '@/components/signup/SocialGoogle';
import Loader, { LoaderContainer } from '@/components/common/Loader';
import OauthButton from '@/components/signup/OauthButton';
import { OAUTH } from '@/constants/oauth';
import { theme } from '@/styles/theme';
import { OAuthType } from '@/types/login';
import { Suspense } from 'react';
import styled from 'styled-components';
import Image from 'next/image';

interface OauthButtonProps {
bgColor: string;
}

const notReady = () => {
alert('준비 중입니다.');
};

const oauthButtons = [
{
key: 'naver',
bgColor: '#03CF5D',
component: (
<Image
src="/assets/icons/ic_naver.svg"
alt="Naver"
width={26}
height={26}
onClick={() => alert('준비 중입니다.')}
/>
)
},
{
key: 'google',
bgColor: '#FFFFFF',
component: <SocialGoogle />
},
{
key: 'kakao',
bgColor: '#FEE500',
component: <SocialKakao />
}
];

export default function Login() {
return (
<Container>
Expand All @@ -48,11 +20,23 @@ export default function Login() {
<LogoText>편지로 수놓는 나의 스페이스</LogoText>
<LogoImage src="/assets/login/login_logo.png" />
<OauthWrapper>
{oauthButtons.map(({ key, bgColor, component }) => (
<OauthButton key={key} bgColor={bgColor}>
{component}
</OauthButton>
))}
<Suspense
fallback={
<LoaderContainer>
<Loader />
</LoaderContainer>
}
>
{OAUTH.map((item) => (
<OauthButton
key={item.key}
loginType={item.key as OAuthType}
bgColor={item.bgColor}
icon={item.icon}
size={item.size}
/>
))}
</Suspense>
</OauthWrapper>
<LetterBtnText onClick={notReady}>
로그인 없이 편지 작성해보기
Expand Down Expand Up @@ -157,20 +141,6 @@ const OauthWrapper = styled.div`
justify-content: center;
`;

const OauthButton = styled.button<OauthButtonProps>`
width: 69px;
height: 69px;
border-radius: 50%;
border: none;
background-color: ${({ bgColor }) => bgColor};
display: flex;
align-items: center;
overflow: hidden;
justify-content: center;
cursor: pointer;
transition: background-color 0.3s;
`;

const LetterBtnText = styled.div`
${(props) => props.theme.fonts.caption02};
color: ${theme.colors.gray400};
Expand Down
36 changes: 8 additions & 28 deletions src/app/mypage/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import { getLetterCount } from '@/api/letter/letter';
import { getUserInfo, logout } from '@/api/mypage/user';
import Button from '@/components/common/Button';
import Loader, { LoaderContainer } from '@/components/common/Loader';
import NavigatorBar from '@/components/common/NavigatorBar';
import { OAUTH } from '@/constants/oauth';
import { theme } from '@/styles/theme';
import { clearOnboarding, clearTokens, getRefreshToken } from '@/utils/storage';
import { useRouter } from 'next/navigation';
Expand Down Expand Up @@ -65,7 +65,6 @@ const MyPage = () => {
setName(response.data.name);
setEmail(response.data.email);
setPlatform(response.data.socialPlatform);
// console.log('회원정보 조회 성공:', response.data);
} catch (error) {
console.error('회원정보 조회 실패:', error);
}
Expand All @@ -81,18 +80,9 @@ const MyPage = () => {
}
};

const EmailType = (platform): string => {
switch (platform) {
case 'GOOGLE':
return '/assets/icons/ic_google.svg';
case 'KAKAO':
return '/assets/icons/ic_kakao_profile.svg';
case 'NAVER':
return '/assets/icons/ic_naver.svg';
default:
return '';
}
};
const profileSrc = OAUTH.find(
(oauth) => oauth.key === platform.toLowerCase()
)?.profile;

return (
<Container>
Expand All @@ -112,11 +102,7 @@ const MyPage = () => {
<ProfileInfo>
<ProfileName>{name}님의 스페이스</ProfileName>
<ProfileEmail>
<StyledIcon
src={EmailType(platform)}
alt="emailIcon"
platform={platform as keyof typeof iconSizes}
/>
<StyledIcon src={profileSrc} alt={platform} />
<div>{email}</div>
</ProfileEmail>
<CountRaw>
Expand Down Expand Up @@ -258,15 +244,9 @@ const ProfileImage = styled.img`
}
`;

const iconSizes = {
GOOGLE: 20,
KAKAO: 20,
NAVER: 20
} as const;

const StyledIcon = styled.img<{ platform: keyof typeof iconSizes }>`
width: ${({ platform }) => iconSizes[platform]}px;
height: ${({ platform }) => iconSizes[platform]}px;
const StyledIcon = styled.img`
width: 20px;
height: 20px;
`;

const ProfileInfo = styled.div`
Expand Down
2 changes: 0 additions & 2 deletions src/app/signup/complete/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ const Container = styled.div`
width: 100%;
max-width: 393px;
height: 100%;
max-height: 853px;
flex-direction: column;
//overflow: scroll;
justify-content: space-between;
background-image: url('/assets/signup/signup_bg.png');
background-size: cover;
Expand Down
Loading