Skip to content

Commit dfe596e

Browse files
authored
fix/메인페이지 아코디언박스 오류 수정 (#151)
* [refactor] 무한스크롤 tanstack * [refactor] 레시피페이지 리팩토링 * [refactor] 아코디언박스 * [feat]필터링 뒤로가기 스크롤 저장 * [chore] 머지 전 커밋 * [chore]머지 전 커밋 누락 내용 커밋 * [refactor]리팩토링 커밋 * [refactor] 정렬 중복아이템문제 * [feat] 칵테일 정렬기능 * [fix]댓글 알림 수정 * [chore] 충돌사항 수정 * [docs] 필요없는 폰트파일 정리 * [feat]sse설정 * [feat]sse알림설정 * [chore]머지후 커밋 * [style] 메인페이지 아코디언 오류 수정 * [feat]알림 SSE기능
1 parent b3ceb95 commit dfe596e

File tree

7 files changed

+98
-22
lines changed

7 files changed

+98
-22
lines changed

src/app/layout.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import '@/shared/styles/global.css';
22
import type { Metadata } from 'next';
3-
import '@/shared/styles/global.css';
43
import { Toaster } from 'react-hot-toast';
54
import ScrollTopBtnWrapper from '@/shared/components/scroll-top/ScrollTopBtnWrapper';
65
import KaKaoScript from './api/kakao/KaKaoScript';
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { useEffect, useRef, useState } from 'react';
2+
import { getApi } from '@/app/api/config/appConfig';
3+
4+
export function useSSENotification(isLoggedIn: boolean) {
5+
const [hasNewNotification, setHasNewNotification] = useState(false);
6+
const eventSourceRef = useRef<EventSource | null>(null);
7+
const isConnectingRef = useRef(false);
8+
9+
useEffect(() => {
10+
// 로그인 안 했으면 연결 안 함
11+
if (!isLoggedIn) {
12+
if (eventSourceRef.current) {
13+
eventSourceRef.current.close();
14+
eventSourceRef.current = null;
15+
isConnectingRef.current = false;
16+
}
17+
return;
18+
}
19+
20+
// 이미 연결 중이거나 연결되어 있으면 중복 방지
21+
if (isConnectingRef.current || eventSourceRef.current) {
22+
return;
23+
}
24+
25+
isConnectingRef.current = true;
26+
27+
const eventSource = new EventSource(`${getApi}/me/subscribe`, {
28+
withCredentials: true,
29+
});
30+
31+
eventSourceRef.current = eventSource;
32+
33+
eventSource.onopen = () => {
34+
isConnectingRef.current = false;
35+
};
36+
37+
eventSource.onmessage = () => {
38+
setHasNewNotification(true);
39+
};
40+
41+
eventSource.onerror = () => {
42+
isConnectingRef.current = false;
43+
44+
if (eventSource.readyState === EventSource.CLOSED) {
45+
eventSourceRef.current = null;
46+
}
47+
};
48+
49+
// cleanup 함수
50+
return () => {
51+
if (eventSourceRef.current) {
52+
eventSourceRef.current.close();
53+
eventSourceRef.current = null;
54+
}
55+
isConnectingRef.current = false;
56+
};
57+
}, [isLoggedIn]); // isLoggedIn만 의존성으로
58+
59+
const clearNotification = () => {
60+
setHasNewNotification(false);
61+
};
62+
63+
return { hasNewNotification, clearNotification };
64+
}

src/domains/main/components/mainSlide/components/mobile/MobileAbv.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ function MobileAbv() {
5353
<h2 className="text-xl sm:text-2xl font-black text-white">내 알콜도수 UP</h2>
5454
<button
5555
type="button"
56-
className={clsx(`block duration-300 sm:hidden`, isClick ? 'rotate-135' : 'rotate-0')}
56+
className={clsx(
57+
`block z-1 duration-300 sm:hidden`,
58+
isClick ? 'rotate-[135deg]' : 'rotate-0'
59+
)}
5760
onClick={() => setIsClick(!isClick)}
5861
>
5962
<Add />

src/domains/main/components/mainSlide/components/mobile/MobileSlideCommunity.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ function MobileSlideCommunity() {
1616
<h2 className="text-xl sm:text-2xl font-black text-white">함께 나누는 칵테일 이야기</h2>
1717
<button
1818
type="button"
19-
className={clsx(`block duration-300 sm:hidden`, isClick ? 'rotate-135' : 'rotate-0')}
19+
className={clsx(
20+
`block duration-300 z-1 sm:hidden`,
21+
isClick ? 'rotate-[135deg]' : 'rotate-0'
22+
)}
2023
onClick={() => setIsClick(!isClick)}
2124
>
2225
<Add />

src/domains/main/components/mainSlide/components/mobile/MobileSlideTest.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ function MobileSlideTest() {
2525
<h2 className="text-xl sm:text-2xl font-black text-white">AI기반 취향테스트</h2>
2626
<button
2727
type="button"
28-
className={clsx(`block duration-300 sm:hidden`, isClick ? 'rotate-135' : 'rotate-0')}
29-
onClick={() => setIsClick(!isClick)}
28+
className={clsx(
29+
`block duration-300 z-1 sm:hidden`,
30+
isClick ? 'rotate-[135deg]' : 'rotate-0'
31+
)}
32+
onClick={() => {
33+
setIsClick(!isClick);
34+
}}
3035
>
31-
<Add />
36+
<Add className="pointer-events-none" />
3237
</button>
3338
</header>
3439
<div

src/domains/mypage/components/pages/my-active/MyLike.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,6 @@ function MyLike() {
2020
fetchLike();
2121
}, []);
2222

23-
useEffect(() => {
24-
console.log(myLike);
25-
}, [myLike]);
26-
27-
return (
28-
<section className="flex justify-center">
29-
{myLike.length > 0 ? (
30-
<PostCard posts={myLike} isLoading={isLoading} />
31-
) : (
32-
<div>아직 좋아요를 누른 글이 없습니다</div>
33-
)}
34-
</section>
35-
);
23+
return <PostCard posts={myLike} isLoading={isLoading} />;
3624
}
3725
export default MyLike;

src/shared/components/header/HeaderBtn.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,34 @@ import { useAuthStore } from '@/domains/shared/store/auth';
88
import { setPreLoginPath } from '@/domains/shared/auth/utils/setPreLoginPath';
99
import { useState } from 'react';
1010
import LogoutConfirm from '@/domains/login/components/LogoutConfirm';
11+
import { useSSENotification } from '@/domains/main/api/useSSENotification';
1112

1213
function HeaderBtn({ pathname }: { pathname: string }) {
1314
const { isLoggedIn } = useAuthStore();
1415
const router = useRouter();
1516
const [logoutModalOpen, setLogoutModalOpen] = useState(false);
1617

18+
const { hasNewNotification, clearNotification } = useSSENotification(isLoggedIn);
19+
1720
const navButtons = [
1821
{
1922
icon: Bell,
2023
label: '알림',
2124
className: pathname === '/mypage/my-alarm' ? 'text-tertiary' : 'text-current',
2225
hiddenMobile: true,
23-
onClick: () => router.push('/mypage/my-alarm'),
26+
onClick: () => {
27+
clearNotification();
28+
router.push('/mypage/my-alarm');
29+
},
30+
showBadge: true,
2431
},
2532
{
2633
icon: User,
2734
label: '마이 페이지',
2835
className: pathname === '/mypage' ? 'text-tertiary' : 'text-current',
2936
hiddenMobile: true,
3037
onClick: () => router.push('/mypage'),
38+
showBadge: false,
3139
},
3240
];
3341

@@ -50,18 +58,24 @@ function HeaderBtn({ pathname }: { pathname: string }) {
5058
{/* 아이콘 버튼들 */}
5159
<div className="flex gap-2">
5260
{isLoggedIn &&
53-
navButtons.map(({ icon: Icon, label, onClick, className, hiddenMobile }) => (
61+
navButtons.map(({ icon: Icon, label, onClick, className, hiddenMobile, showBadge }) => (
5462
<button
5563
key={label}
5664
aria-label={label}
5765
onClick={onClick}
5866
className={tw(
5967
className,
6068
hiddenMobile ? 'hidden sm:flex' : '',
61-
'items-center justify-center rounded-full w-7 h-7 hover:bg-secondary/10 transition-colors duration-200'
69+
'relative items-center justify-center rounded-full w-7 h-7 hover:bg-secondary/10 transition-colors duration-200'
6270
)}
6371
>
6472
<Icon width={24} height={24} className="text-current" />
73+
{showBadge && hasNewNotification && (
74+
<span
75+
className=" absolute items-center justify-center top-1 right-1 w-2 h-2 bg-red-500
76+
rounded-full"
77+
></span>
78+
)}
6579
</button>
6680
))}
6781
</div>

0 commit comments

Comments
 (0)