diff --git a/apps/what-today/src/components/notification/NotificationPopover.tsx b/apps/what-today/src/components/notification/NotificationPopover.tsx index db5602a4..b7d84fc9 100644 --- a/apps/what-today/src/components/notification/NotificationPopover.tsx +++ b/apps/what-today/src/components/notification/NotificationPopover.tsx @@ -1,5 +1,13 @@ import { useInfiniteQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import { BellIcon, Button, DotIcon, NotificationCard, Popover, useToast } from '@what-today/design-system'; +import { + BellIcon, + Button, + DotIcon, + NotificationCard, + NotificationCardSkeleton, + Popover, + useToast, +} from '@what-today/design-system'; import type { AxiosError } from 'axios'; import { useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; @@ -129,10 +137,17 @@ export default function NotificationPopover({ isMobile }: NotificationPopoverPro -

알림 {data?.pages[0].totalCount}개

+

알림 {data?.pages[0].totalCount ?? 0}개

-
- {isLoading &&

Loading...

} +
+ {isLoading && ( + <> + + + + + + )}
{data?.pages.map((page) => page.notifications.map((notification) => ( @@ -152,7 +167,8 @@ export default function NotificationPopover({ isMobile }: NotificationPopoverPro

알림이 없습니다.

)}
{/* 무한 스크롤 감지용 */} -
+ {isFetchingNextPage && } +
); diff --git a/packages/design-system/src/components/NotificationCard.tsx b/packages/design-system/src/components/NotificationCard.tsx index 94a401c7..272997de 100644 --- a/packages/design-system/src/components/NotificationCard.tsx +++ b/packages/design-system/src/components/NotificationCard.tsx @@ -60,12 +60,16 @@ const parseNotificationContent = (content: string): ParsedNotification | null => export default function NotificationCard({ content, onDelete, onClickDetail }: NotificationCardProps) { const parsedNotification = parseNotificationContent(content); + const handleClickStop = (e: React.MouseEvent) => { + e.stopPropagation(); + }; + // parsedNotification 실패시 기본 content를 메시지로 보여줍니다. if (!parsedNotification) { return (
-

알림

+

알림

@@ -78,29 +82,38 @@ export default function NotificationCard({ content, onDelete, onClickDetail }: N const { title, date, confirm } = parsedNotification; return ( -
+
{ + handleClickStop(e); + onClickDetail(); + }} + >
{confirm ? : } -

- {confirm ? '예약이 승인되었어요!' : '예약이 거절되었어요.'} -

+

{confirm ? '예약이 승인되었어요!' : '예약이 거절되었어요.'}

-
-
-
- -

{title}

-
-
- -

- {date.year}년 {date.month}월 {date.day}일 {date.startTime}~{date.endTime} -

-
+
+ +

{title}

+
+
+ +

+ {date.year}년 {date.month}월 {date.day}일 {date.startTime}~{date.endTime} +

); diff --git a/packages/design-system/src/components/skeleton/NotificationCardSkeleton.tsx b/packages/design-system/src/components/skeleton/NotificationCardSkeleton.tsx new file mode 100644 index 00000000..999754c2 --- /dev/null +++ b/packages/design-system/src/components/skeleton/NotificationCardSkeleton.tsx @@ -0,0 +1,26 @@ +export default function NotificationCardSkeleton() { + return ( +
+ {/* 상단: 상태 뱃지 + 문구 + 삭제 버튼 */} +
+
+
+
+
+
+
+ + {/* 제목 (아이콘 + 텍스트) */} +
+
+
+
+ + {/* 날짜 및 시간 (아이콘 + 텍스트) */} +
+
+
+
+
+ ); +} diff --git a/packages/design-system/src/components/skeleton/index.tsx b/packages/design-system/src/components/skeleton/index.tsx index cb65c034..015d3644 100644 --- a/packages/design-system/src/components/skeleton/index.tsx +++ b/packages/design-system/src/components/skeleton/index.tsx @@ -1 +1,2 @@ export { default as ExperienceCardSkeleton } from './ExperienceCardSkeleton'; +export { default as NotificationCardSkeleton } from './NotificationCardSkeleton'; diff --git a/packages/design-system/src/pages/NotificationCardDoc.tsx b/packages/design-system/src/pages/NotificationCardDoc.tsx index 3cb15e7e..c4acf1b7 100644 --- a/packages/design-system/src/pages/NotificationCardDoc.tsx +++ b/packages/design-system/src/pages/NotificationCardDoc.tsx @@ -1,5 +1,6 @@ import { useNavigate } from 'react-router-dom'; +import { NotificationCardSkeleton } from '@/components'; import Playground from '@/layouts/Playground'; import NotificationCard from '../components/NotificationCard'; @@ -55,6 +56,7 @@ Header의 알림창 팝오버에서 보여지며, 알림은 개별 삭제 가능 onClickDetail={() => navigate('/mypage/reservations-list')} onDelete={() => alert('삭제 API 요청')} /> + navigate('/mypage/reservations-list')}