Skip to content

Commit d8511ff

Browse files
committed
[text] 로그인 기능구현중 테스트
1 parent e0bd876 commit d8511ff

File tree

12 files changed

+118
-112
lines changed

12 files changed

+118
-112
lines changed

src/app/login/first-user/page.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import LoginRedirectHandler from '@/shared/components/auth/LoginRedirectHandler';
2+
3+
function Page() {
4+
return <LoginRedirectHandler />;
5+
}
6+
7+
export default Page;

src/app/login/success/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import LoginRedirectHandler from '@/shared/components/auth/LoginRedirectHandler';
2+
3+
function Page() {
4+
return <LoginRedirectHandler />;
5+
}
6+
export default Page;

src/app/oauth/success/page.tsx

Lines changed: 0 additions & 50 deletions
This file was deleted.

src/shared/@store/auth.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ interface User {
55
id: string;
66
email: string;
77
nickname: string;
8-
is_first_login: boolean;
8+
isFirstLogin: boolean;
99
abv_degree?: number;
1010
provider?: 'naver' | 'kakao' | 'google';
1111
}
@@ -39,7 +39,7 @@ export const useAuthStore = create<AuthState>((set) => ({
3939

4040
logout: async () => {
4141
try {
42-
await fetch('http://localhost:8080/api/user/auth/logout', {
42+
await fetch('http://localhost:8080/user/auth/logout', {
4343
method: 'POST',
4444
credentials: 'include',
4545
});
@@ -54,7 +54,7 @@ export const useAuthStore = create<AuthState>((set) => ({
5454

5555
updateUser: async () => {
5656
try {
57-
const res = await fetch('http://localhost:8080/api/user/auth/refresh', {
57+
const res = await fetch('http://localhost:8080/user/auth/refresh', {
5858
method: 'POST',
5959
credentials: 'include',
6060
headers: { 'Content-Type': 'application/json' },
@@ -63,12 +63,15 @@ export const useAuthStore = create<AuthState>((set) => ({
6363
if (!res.ok) throw new Error('토큰 갱신 실패');
6464
const data = await res.json();
6565

66-
console.log(data);
67-
// if (data.accessToken && data.user) {
68-
// set({ accessToken: data.accessToken, user: data.user, isLoggedIn: true });
69-
// console.log('토큰 및 유저 정보 갱신 완료:', data.user);
70-
// return data.user;
71-
// }
66+
console.log('updateUser response:', data);
67+
const userInfo = data?.data?.user;
68+
const accessToken = data?.data?.accessToken;
69+
70+
if (userInfo && accessToken) {
71+
set({ user: userInfo, accessToken, isLoggedIn: true });
72+
console.log('토큰 및 유저 정보 갱신 완료:', userInfo);
73+
return userInfo;
74+
}
7275

7376
return null;
7477
} catch (err) {

src/shared/@store/modal.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,29 @@ interface WelcomeModalData {
55
nickname: string;
66
}
77

8+
interface LogoutConfirmModalData {
9+
open: boolean;
10+
}
11+
812
interface ModalStore {
913
welcomeModal: WelcomeModalData;
14+
logoutConfirmModal: LogoutConfirmModalData;
1015

1116
openWelcomeModal: (nickname: string) => void;
1217
closeWelcomeModal: () => void;
18+
19+
openLogoutConfirmModal: () => void;
20+
closeLogoutConfirmModal: () => void;
1321
}
1422

1523
export const useModalStore = create<ModalStore>((set) => ({
1624
welcomeModal: { open: false, nickname: '' },
25+
logoutConfirmModal: { open: false },
1726

1827
openWelcomeModal: (nickname: string) => set({ welcomeModal: { open: true, nickname } }),
1928

2029
closeWelcomeModal: () => set({ welcomeModal: { open: false, nickname: '' } }),
30+
31+
openLogoutConfirmModal: () => set({ logoutConfirmModal: { open: true } }),
32+
closeLogoutConfirmModal: () => set({ logoutConfirmModal: { open: false } }),
2133
}));
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
function LoginConfirm() {
2+
return <div>LoginConfirm</div>;
3+
}
4+
export default LoginConfirm;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import { usePathname, useRouter } from 'next/navigation';
5+
import { useAuthStore } from '@/shared/@store/auth';
6+
import { useModalStore } from '@/shared/@store/modal';
7+
import { customToast } from '@/shared/components/toast/CustomToastUtils';
8+
import Spinner from '../spinner/Spinner';
9+
10+
function LoginRedirectHandler() {
11+
const pathname = usePathname();
12+
const router = useRouter();
13+
const { user, updateUser } = useAuthStore();
14+
const { openWelcomeModal } = useModalStore();
15+
const [loading, setLoading] = useState(true);
16+
17+
useEffect(() => {
18+
if (!user && loading) {
19+
updateUser()
20+
.then((fetchedUser) => {
21+
if (!fetchedUser) {
22+
router.replace('/login');
23+
}
24+
})
25+
.catch(() => {
26+
router.replace('/login');
27+
})
28+
.finally(() => setLoading(false));
29+
}
30+
}, [user, loading, updateUser, router]);
31+
32+
useEffect(() => {
33+
if (!user || loading) return;
34+
35+
const preLoginPath = sessionStorage.getItem('preLoginPath') || '/';
36+
37+
if (pathname.startsWith('/login/first-user')) {
38+
openWelcomeModal(user.nickname);
39+
} else if (pathname.startsWith('/login/success')) {
40+
customToast.success(`${user.nickname}님 \n 로그인 성공 🎉`);
41+
router.replace(preLoginPath);
42+
}
43+
}, [pathname, user, router, openWelcomeModal, loading]);
44+
45+
if (loading) {
46+
return (
47+
<div className="page-layout max-w-824 flex-center">
48+
<Spinner />
49+
</div>
50+
);
51+
}
52+
53+
return null;
54+
}
55+
export default LoginRedirectHandler;

src/app/login/Welcome.tsx renamed to src/shared/components/auth/Welcome.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,29 @@ import Button from '@/shared/components/button/Button';
66
import ModalLayout from '@/shared/components/modalPop/ModalLayout';
77
import Ssury from '@/shared/assets/ssury/ssury_jump.webp';
88
import { useRouter } from 'next/navigation';
9+
import { useModalStore } from '@/shared/@store/modal';
10+
import { useAuthStore } from '@/shared/@store/auth';
911

10-
interface Props {
11-
open: boolean;
12-
onClose: () => void;
13-
nickname: string;
14-
}
15-
16-
function Welcome({ open, onClose, nickname }: Props) {
12+
function Welcome() {
1713
const router = useRouter();
14+
const { user } = useAuthStore();
15+
const { welcomeModal, closeWelcomeModal } = useModalStore();
16+
17+
if (!welcomeModal.open || !user) return null;
1818

1919
return (
2020
<ModalLayout
21-
open={open}
22-
onClose={onClose}
23-
title={`환영합니다, ${nickname}님!`}
21+
open={welcomeModal.open}
22+
onClose={closeWelcomeModal}
23+
title={`환영합니다, ${user.nickname}님!`}
2424
description="바텐더 쑤리가 안내해드릴게요"
2525
buttons={
2626
<>
2727
<Button
2828
type="button"
2929
color="purple"
3030
onClick={() => {
31-
onClose();
31+
closeWelcomeModal();
3232
router.push('/recipe');
3333
}}
3434
>
@@ -37,7 +37,7 @@ function Welcome({ open, onClose, nickname }: Props) {
3737
<Button
3838
type="button"
3939
onClick={() => {
40-
onClose();
40+
closeWelcomeModal();
4141
router.push('/recommend');
4242
}}
4343
>

src/shared/components/header/DropdownMenu.tsx

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -103,42 +103,6 @@ function DropdownMenu({ isClicked, setIsClicked }: Props) {
103103
))}
104104
</ul>
105105

106-
<section
107-
aria-label="로그인 로그아웃"
108-
className="border border-t-[1px] border-t-gray flex items-center py-[32px] gap-2"
109-
>
110-
<User color="var(--color-primary)" />
111-
<button type="button" className="text-black font-light text-xl hover:text-black/70">
112-
로그인/회원가입
113-
</button>
114-
</section>
115-
116-
<div className="my-5">
117-
<ul className="flex flex-col gap-[12px] text-black px-2">
118-
{navItem.map(({ label, href }, idx) => (
119-
<li className={`font-normal ${pathname === href ? '' : 'px-3 py-[12px]'}`} key={href}>
120-
<Link
121-
href={href}
122-
onNavigate={() => setIsClicked(false)}
123-
className={`items-start ${pathname === href ? 'bg-tertiary/70 inline-flex pr-5 p-2 rounded-md text-secondary' : 'hover:text-black/70 flex'}`}
124-
aria-current={pathname === href ? 'page' : undefined}
125-
>
126-
<span className="text-[20px] mr-3">{idx + 1}. </span>
127-
<span
128-
className="text-[28px]"
129-
ref={(el) => {
130-
textRef.current[idx] = el;
131-
}}
132-
onMouseEnter={() => handleMouseEnter(idx)}
133-
onMouseLeave={() => handleMouseLeave(idx)}
134-
>
135-
{label}
136-
</span>
137-
</Link>
138-
</li>
139-
))}
140-
</ul>
141-
</div>
142106
<div className="border border-t-[1px] border-t-gray flex items-center py-[32px] gap-2">
143107
{isLoggedIn ? (
144108
<button
@@ -163,16 +127,16 @@ function DropdownMenu({ isClicked, setIsClicked }: Props) {
163127
</Link>
164128
)}
165129
</div>
130+
166131
<div className="absolute top-1.5 left-3">
167132
<button
168133
type="button"
169-
aria-label="모바일 메뉴 닫기"
134+
aria-label="메인 네비게이션 메뉴 닫기"
170135
onClick={() => {
171136
setIsClicked(false);
172137
}}
173-
aria-label="메인 네비게이션 메뉴 닫기"
174138
>
175-
<Close color="var(--color-primary)" className="w-8 h-8" />
139+
<Close color="var(--color-primary)" className="w-8 h-8" aria-hidden />
176140
</button>
177141
</div>
178142
</nav>

src/shared/components/header/HeaderBtn.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function HeaderBtn({ pathname }: { pathname: string }) {
4848
];
4949

5050
return (
51-
<div className="flex gap-3">
51+
<div className="flex gap-2">
5252
{headerBtn.map(({ icon: Icon, label, onClick, className }) => (
5353
<button
5454
key={label}

0 commit comments

Comments
 (0)