From e747b216694d8ba826b425fc9abee580f28116a4 Mon Sep 17 00:00:00 2001 From: yoooooojin Date: Mon, 27 Jul 2026 02:00:01 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=95=8C=EB=A6=BC=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1=20(api=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/NotificationBell.tsx | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/components/common/NotificationBell.tsx diff --git a/src/components/common/NotificationBell.tsx b/src/components/common/NotificationBell.tsx new file mode 100644 index 0000000..c91ecea --- /dev/null +++ b/src/components/common/NotificationBell.tsx @@ -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(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 ( +
navigate('/alert')} + > + + + {unreadCount > 0 && ( +
+ )} +
+ ); +}; From 63d55c0a06fe0bd585d8f926ee5485cfa94275c5 Mon Sep 17 00:00:00 2001 From: yoooooojin Date: Mon, 27 Jul 2026 02:04:04 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=EB=B9=A8=EA=B0=84=20=EC=A0=90=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98,=20=ED=81=AC=EA=B8=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/NotificationBell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/NotificationBell.tsx b/src/components/common/NotificationBell.tsx index c91ecea..6bdb7b1 100644 --- a/src/components/common/NotificationBell.tsx +++ b/src/components/common/NotificationBell.tsx @@ -51,7 +51,7 @@ export const NotificationBell = () => { {unreadCount > 0 && ( -
+
)}
); From 1b17561d4de62d1191d734e330979127f03e33ae Mon Sep 17 00:00:00 2001 From: yoooooojin Date: Sat, 1 Aug 2026 02:30:05 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=EB=B0=B0=EC=A7=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/Badge.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/common/Badge.tsx b/src/components/common/Badge.tsx index 4fbdf72..3be7909 100644 --- a/src/components/common/Badge.tsx +++ b/src/components/common/Badge.tsx @@ -9,7 +9,11 @@ interface BadgeProps { | 'lightPink' | 'lightYellow' | 'outlineGray' - | 'outlineBlue'; + | 'outlineBlue' + | 'lightRed' + | 'grayOutline' + | 'bluesolid' + | 'lightBlueOutline'; className?: string; // 좔가적인 μ—¬λ°±(ml-2) 등을 쀄 λ•Œ μ‚¬μš© } @@ -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 = ({