Skip to content

Commit 3581736

Browse files
authored
[FIX] 알림 API 수정 및 실시간 알림 뱃지/SSE 연동 (#491)
1 parent e71faa8 commit 3581736

File tree

22 files changed

+242
-97
lines changed

22 files changed

+242
-97
lines changed

frontend/src/api/client/notificationApi.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,18 @@ export async function getNotifications(
2727
return data!;
2828
}
2929

30-
export async function deleteAllNotifications(notificationIds: number[]): Promise<void> {
31-
const { response } = await client.DELETE("/api/notifications", {
32-
params: { query: {} as never },
33-
body: { notificationIds } as never,
34-
});
30+
export async function getUnreadCount(): Promise<number> {
31+
try {
32+
const { data } = await client.GET("/api/notifications/count");
33+
return data?.count ?? 0;
34+
} catch (error) {
35+
console.error("getUnreadCount error:", error instanceof Error ? error.message : error);
36+
return 0;
37+
}
38+
}
39+
40+
export async function deleteAllNotifications(): Promise<void> {
41+
const { response } = await client.DELETE("/api/notifications");
3542

3643
if (!response.ok) {
3744
throw new Error("알림 전체 삭제에 실패했어요.");

frontend/src/api/server/forecastApi.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,18 @@ import type {
66
GetDiseaseCostResponse,
77
GetAIRecommendationResponse,
88
} from "@/api/types/forecastApi.type";
9+
import { isApiHttpError } from "@/api/utils/isApiHttpError";
910

10-
export async function getAIRecommendation(): Promise<GetAIRecommendationResponse> {
11-
const { data } = await client.GET("/api/group/medical/info");
12-
return data as GetAIRecommendationResponse;
11+
export async function getAIRecommendation(): Promise<GetAIRecommendationResponse | null> {
12+
try {
13+
const { data } = await client.GET("/api/group/medical/info");
14+
return data as GetAIRecommendationResponse;
15+
} catch (error) {
16+
if (isApiHttpError(error) && error.status === 404) {
17+
return null;
18+
}
19+
throw error;
20+
}
1321
}
1422

1523
/**

frontend/src/api/types/forecastApi.type.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ export type GetDiseaseRankingResponse = NonNullable<
1919
>;
2020

2121
export type GetDiseaseStatisticsResponse = NonNullable<
22-
components["schemas"]["GroupMedicalStatisticsResponse"]
22+
components["schemas"]["PetMedicalStatisticsResponse"]
2323
>;
2424

2525
export type GetDiseaseCostResponse = NonNullable<
2626
components["schemas"]["TreatmentsResponse"]["treatments"]
2727
>;
2828

2929
export type GetAIRecommendationResponse = NonNullable<
30-
components["schemas"]["GroupMedicalInfoResponse"]
30+
components["schemas"]["PetMedicalInfoResponse"]
3131
>;

frontend/src/app/(sidebar)/forecast/_components/ai-recommendation/AIRecommendationRefresher.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import { useServerEvent } from "@/store/ServerEventProvider";
3+
import { useServerEvent } from "@/hooks/ServerEventProvider";
44
import { useRouter } from "next/navigation";
55
import { useEffect } from "react";
66

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
import type { components } from "@/types/schema";
2-
export type AIRecommendationResponse = NonNullable<
3-
components["schemas"]["GroupMedicalInfoResponse"]
4-
>;
2+
export type AIRecommendationResponse = NonNullable<components["schemas"]["PetMedicalInfoResponse"]>;

frontend/src/app/(sidebar)/forecast/_types/annualDiseaseRisk.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { components } from "@/types/schema";
22
import type { DiseaseCode } from "./disease";
33

4-
export type AnnualDiseases = NonNullable<components["schemas"]["GroupMedicalStatisticsResponse"]>;
4+
export type AnnualDiseases = NonNullable<components["schemas"]["PetMedicalStatisticsResponse"]>;
55

66
export type RiskLineRow = { year: number } & Partial<Record<DiseaseCode, number>>; // Recharts용 row 타입: year + 질병코드별 number
77

frontend/src/app/(sidebar)/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Header from "@/components/layout/Header";
22
import Sidebar from "@/components/layout/Sidebar/SideBar";
33
import SSEListener from "@/app/_components/SSEListener";
4-
import { ServerEventProvider } from "@/store/ServerEventProvider";
4+
import { ServerEventProvider } from "@/hooks/ServerEventProvider";
55

66
export default function SidebarLayout({
77
children,

frontend/src/app/(sidebar)/saving/_hooks/useSSESaving.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

33
import { useEffect, useRef } from "react";
4-
import { useServerEvent } from "@/store/ServerEventProvider";
4+
import { useServerEvent } from "@/hooks/ServerEventProvider";
55
import { useSavingStatus } from "@/app/(sidebar)/saving/_hooks/useSavingStatus";
66
import { getBank } from "@/api/client/savingApi";
77

frontend/src/app/_components/SSEListener.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useToast } from "@/components/ui/Toast/ToastProvider";
44
import { useSSE } from "@/hooks/useSSE";
55
import { useSSEToken } from "@/hooks/useSSEToken";
66
import { getSSENotificationMessage } from "@/lib/sse/sseNotification";
7-
import { useServerEvent } from "@/store/ServerEventProvider";
7+
import { useServerEvent } from "@/hooks/ServerEventProvider";
88
import type { SSEEvent } from "@/types/sse";
99
import { useCallback } from "react";
1010
import { EVENT_TOAST_DURATION } from "@/constants/sseConnection";

frontend/src/components/layout/Notification/NotificationCard.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import { NotificationItem } from "./notification.type";
66

77
export default function NotificationCard({
88
item,
9+
index,
910
onDelete,
1011
}: {
1112
item: NotificationItem;
13+
index: number;
1214
onDelete: (id: number) => void;
1315
}) {
1416
const icon =
@@ -19,7 +21,7 @@ export default function NotificationCard({
1921
);
2022

2123
return (
22-
<div className="flex flex-col border-b border-gray-100 px-[30px] py-[12px]">
24+
<div className={`flex flex-col px-[30px] py-[12px] ${index % 2 === 1 ? "bg-gray-50" : ""}`}>
2325
<div className="flex items-center justify-between">
2426
<div className="flex items-center gap-[18px]">
2527
<div

0 commit comments

Comments
 (0)