Skip to content

Commit 64ef4f4

Browse files
authored
Merge pull request #135 from codeit-2team/feat/134
Feat/134 알림 클릭 시 예약 내역 페이지로 이동
2 parents eceab37 + 8725c7d commit 64ef4f4

File tree

4 files changed

+52
-21
lines changed

4 files changed

+52
-21
lines changed

src/components/Notification/NotificationCard.tsx

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { useDeleteNotification } from '@/hooks/useDeleteNotification';
44
import cn from '@/lib/cn';
55
import relativeTime from '@/utils/relativeTime';
66
import IconClose from '@assets/svg/close';
7+
import { useRouter } from 'next/navigation';
8+
import { toast } from 'sonner';
79

810
type NotificationStatus = 'confirmed' | 'declined';
911

@@ -12,6 +14,7 @@ interface NotificationCardProps {
1214
id: number;
1315
createdAt: string;
1416
onDelete: (id: number) => void;
17+
onCardClick?: () => void;
1518
}
1619

1720
const statusColorMap: Record<
@@ -50,14 +53,16 @@ export default function NotificationCard({
5053
createdAt,
5154
id,
5255
onDelete,
56+
onCardClick,
5357
}: NotificationCardProps) {
54-
const { mutate: deleteNotification } = useDeleteNotification();
58+
const { mutateAsync: deleteNotification } = useDeleteNotification();
59+
const router = useRouter();
5560

5661
const formattedContent = content.replace(/(\(\d{4}-\d{2}-\d{2})\s+/, '$1\n');
5762

58-
const handleDelete = () => {
63+
const handleDelete = async () => {
64+
await deleteNotification(id);
5965
onDelete(id);
60-
deleteNotification(id);
6166
};
6267

6368
const keywordMatch = Object.entries(statusKeywordMap).find(([k]) =>
@@ -66,6 +71,19 @@ export default function NotificationCard({
6671

6772
const status = keywordMatch?.[1];
6873

74+
const handleCardClick = async () => {
75+
try {
76+
await deleteNotification(id);
77+
onDelete(id);
78+
onCardClick?.();
79+
router.push('/mypage/reservations');
80+
} catch {
81+
toast.error(
82+
'알림 확인 중 문제가 발생했습니다. 잠시 후 다시 시도해 주세요.',
83+
);
84+
}
85+
};
86+
6987
return (
7088
<div className='w-full rounded-[5px] border border-gray-400 bg-white px-12 py-16'>
7189
<div className='flex items-start justify-between'>
@@ -79,8 +97,8 @@ export default function NotificationCard({
7997
)}
8098
<button
8199
onClick={(e) => {
100+
e.stopPropagation();
82101
setTimeout(() => {
83-
e.stopPropagation();
84102
handleDelete();
85103
}, 0);
86104
}}
@@ -90,23 +108,25 @@ export default function NotificationCard({
90108
</button>
91109
</div>
92110

93-
<p className='text-md font-regular whitespace-pre-line text-black'>
94-
{formattedContent.split(/(|)/).map((text, i) => {
95-
const matchedStatus = statusKeywordMap[text];
96-
return (
97-
<span
98-
key={i}
99-
className={cn(
100-
matchedStatus && statusColorMap[matchedStatus].text,
101-
)}
102-
>
103-
{text}
104-
</span>
105-
);
106-
})}
107-
</p>
111+
<div className='cursor-pointer' onClick={handleCardClick}>
112+
<p className='text-md font-regular whitespace-pre-line text-black'>
113+
{formattedContent.split(/(|)/).map((text, i) => {
114+
const matchedStatus = statusKeywordMap[text];
115+
return (
116+
<span
117+
key={i}
118+
className={cn(
119+
matchedStatus && statusColorMap[matchedStatus].text,
120+
)}
121+
>
122+
{text}
123+
</span>
124+
);
125+
})}
126+
</p>
108127

109-
<p className='mt-4 text-xs text-gray-600'>{relativeTime(createdAt)}</p>
128+
<p className='mt-4 text-xs text-gray-600'>{relativeTime(createdAt)}</p>
129+
</div>
110130
</div>
111131
);
112132
}

src/components/Notification/NotificationCardList.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { toast } from 'sonner';
88

99
type NotificationCardListProps = {
1010
notification: Notification['notifications'];
11+
onCardClick?: () => void;
1112
};
1213

1314
/**
@@ -26,6 +27,7 @@ type NotificationCardListProps = {
2627
*/
2728
export default function NotificationCardList({
2829
notification,
30+
onCardClick,
2931
}: NotificationCardListProps) {
3032
// 현재 화면에 표시할 알림 목록 상태
3133
const [currentNotifications, setCurrentNotifications] =
@@ -143,6 +145,7 @@ export default function NotificationCardList({
143145
prev.filter((item) => item.id !== id),
144146
)
145147
}
148+
onCardClick={onCardClick}
146149
/>
147150
))}
148151

src/components/Notification/NotificationDropdown.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ export default function NotificationDropdown({
6868
)}
6969

7070
{!isLoading && data && (
71-
<NotificationCardList notification={data.notifications} />
71+
<NotificationCardList
72+
notification={data.notifications}
73+
onCardClick={onClose}
74+
/>
7275
)}
7376
</div>
7477
);

src/hooks/useDeleteNotification.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { privateInstance } from '@/apis/privateInstance';
22
import { useMutation, useQueryClient } from '@tanstack/react-query';
3+
import { toast } from 'sonner';
34

45
/**
56
* 특정 알림을 삭제하는 비동기 함수입니다.
@@ -40,5 +41,9 @@ export const useDeleteNotification = () => {
4041
onSuccess: () => {
4142
queryClient.invalidateQueries({ queryKey: ['notifications'] });
4243
},
44+
45+
onError: () => {
46+
toast.error('알림 삭제를 실패했습니다.');
47+
},
4348
});
4449
};

0 commit comments

Comments
 (0)