diff --git a/src/components/ui/modal/notification/Notification.tsx b/src/components/ui/modal/notification/Notification.tsx index 78e0674..ae22e6c 100644 --- a/src/components/ui/modal/notification/Notification.tsx +++ b/src/components/ui/modal/notification/Notification.tsx @@ -1,14 +1,12 @@ import Icon from '@/components/ui/icon/icon'; +import useClickOutside from '@/hooks/useClickOutside'; +import useEscapeKey from '@/hooks/useEscapeKey'; import { cn } from '@/lib/utils/cn'; import { Notice } from '@/types/notice'; import { Shop } from '@/types/shop'; -import { useState } from 'react'; +import { useRef, useState } from 'react'; import NotificationMessage from './NotificationMessage'; -const NOTI_STYLE = { - controlled: '', - uncontrolled: '', -}; export interface Alert { id: string; createdAt: string; @@ -29,11 +27,24 @@ export default function Notification({ alerts, onRead, isOpen, onClose }: Notifi const controlled = typeof isOpen === 'boolean'; const [internalOpen, setInternalOpen] = useState(false); const open = controlled ? (isOpen as boolean) : internalOpen; + const panelRef = useRef(null); const notificationCount = alerts.filter(alert => !alert.read).length; const SORTED_ALERTS = [...alerts].sort( (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() ); + // 외부 클릭 및 ESC 키로 닫기 + const close = () => (controlled ? onClose?.() : setInternalOpen(false)); + useClickOutside(panelRef, () => { + if (!open) return; + close(); + }); + useEscapeKey(e => { + if (!open) return; + e.stopPropagation(); + close(); + }); + return ( <> {!controlled && ( @@ -55,6 +66,8 @@ export default function Notification({ alerts, onRead, isOpen, onClose }: Notifi
알림이 없습니다.

) : ( -
+
{SORTED_ALERTS.map(alert => ( ))}