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
13 changes: 9 additions & 4 deletions src/components/common/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ interface BadgeProps {
| 'lightPink'
| 'lightYellow'
| 'outlineGray'
| 'outlineBlue';
| 'outlineBlue'
| 'lightRed'
| 'grayOutline'
| 'bluesolid'
| 'lightBlueOutline';
className?: string; // 추가적인 여백(ml-2) 등을 줄 때 사용
}

Expand All @@ -21,12 +25,13 @@ const badgeVariants = {
lightYellow: 'bg-yellow-main text-[#CA8A04] border border-[#FEF08A]', // 연노랑 바탕 + 노랑 글씨 (교양필수)
outlineBlue: 'bg-white border border-brand-lightBlue text-brand-lightBlue', // 흰 바탕 + 파란 테두리 + 파란 글씨 (요청받은 게시글)
outlineGray: 'bg-white border border-gray-300 text-gray-600', // 흰 바탕 + 회색 테두리
lightRed: 'bg-red-100 text-red-100 border text-gray-600',
grayOutline: 'bg-gray-200 text-zinc-900 text-xs border border-slate-400 ', // 교양필수
lightRed:
'bg-red-100 text-zinc-900 border text-gray-600 border-neutral-400 font-normal ',
grayOutline: 'bg-gray-200 text-zinc-900 text-sm border border-slate-400 ', // 교양필수
bluesolid:
'bg-brand-lightBlue text-white text-xs font-light border border-slate-500 font-normal', // 졸업요건
lightBlueOutline:
'bg-blue-100 text-zinc-900 border text-xs border-brand-lightBlue ', //전공필수
'bg-brand-soft text-zinc-900 border text-gray-600 text-xs border-neutral-400 font-normal', //전공필수
};

export const Badge = ({
Expand Down
58 changes: 58 additions & 0 deletions src/components/common/NotificationBell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ICONS } from '@/constants/icons';
import { IconButton } from '@/components/common/IconButton';

export const NotificationBell = () => {
const navigate = useNavigate();
const [unreadCount, setUnreadCount] = useState<number>(0);

useEffect(() => {
const fetchUnreadCount = async () => {
try {
const token = localStorage.getItem('accessToken');
const response = await fetch(
'https://swapclass.duckdns.org/api/notifications/unread-count',
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
},
);

const result = await response.json();

// 💡 백엔드 응답(result.success)이 성공이고, data 객체가 존재할 때
if (result.success && result.data) {
// result.data가 { "typeA": 1, "typeB": 2 } 형태이므로,
// Object.values로 숫자 배열([1, 2])만 뽑아낸 뒤 모두 더해줍니다.
const totalCount = Object.values(result.data).reduce(
(sum: number, current: any) => sum + (Number(current) || 0),
0,
);

setUnreadCount(totalCount);
}
} catch (error) {
console.error('알림 개수 조회 실패:', error);
}
};

fetchUnreadCount();
}, []);

return (
<div
className="relative cursor-pointer mt-1"
onClick={() => navigate('/alert')}
>
<IconButton icon={ICONS.BELL} />

{unreadCount > 0 && (
<div className="absolute top-2.5 left-1.5 w-1 h-1 bg-point-red rounded-full" />
)}
</div>
);
};
Loading