Skip to content

feat: SP1 알림배지 제거 api 연결#379

Merged
heesunee merged 3 commits intodevelopfrom
feat/#378/read-alarms
Sep 7, 2025
Merged

feat: SP1 알림배지 제거 api 연결#379
heesunee merged 3 commits intodevelopfrom
feat/#378/read-alarms

Conversation

@bongtta
Copy link
Contributor

@bongtta bongtta commented Sep 7, 2025

#️⃣ Related Issue

Closes #378

💎 PR Point

  • 기존 로직('요청 수락하기', '채팅방 입장하기' 버튼 클릭 시 알림배지 제거) 삭제
  • 매칭 현황 탭 클릭 시 알림배지 제거

📸 Screenshot

2025-09-08.2.05.53.mov

Summary by CodeRabbit

  • 신기능
    • 매칭 탭으로 이동할 때 읽지 않은 알림이 있으면 자동으로 전체 읽음 처리되어 알림 배지가 즉시 정리됩니다.
    • 매칭 수락 후 상황에 따라 바로 적절한 화면으로 이동합니다: 그룹 매칭은 그룹 경로로, 1:1 매칭은 성공 화면으로 안내됩니다.
    • 매칭 수락 이후 단일·그룹 매칭 상태를 모두 새로고침하여 관련 화면의 정보가 즉시 최신 상태로 반영됩니다.

@bongtta bongtta self-assigned this Sep 7, 2025
@bongtta bongtta added the feat new feature label Sep 7, 2025
@bongtta bongtta added the 채은 label Sep 7, 2025
@bongtta bongtta requested a review from yeeeww as a code owner September 7, 2025 17:09
@bongtta bongtta linked an issue Sep 7, 2025 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Sep 7, 2025

Walkthrough

알림 읽음 처리 방식을 개별(matchId)에서 전체 일괄로 변경하고, 관련 엔드포인트·쿼리키·뮤테이션을 교체했습니다. 매칭 수신 화면에서 수락 플로우는 알림 읽기 호출을 제거하고 내비게이션 분기만 남겼습니다. 하단 내비게이션에서 MATCH 탭 진입 시 미읽음이 있으면 전체 읽음 API를 호출합니다.

Changes

Cohort / File(s) Change Summary
Alarm API 전환 (개별→전체 읽음)
src/shared/apis/alarm/alarm-mutations.ts, src/shared/constants/api.ts, src/shared/constants/query-key.ts
READ_ALARM 제거, READ_ALL_ALARMS 추가. 엔드포인트에 POST_READ_ALL_ALARMS: '/v2/users/alarms' 도입. 쿼리키 ALARM_KEY.READ_ALL() 추가(READ 대체). 뮤테이션 시그니처가 인자 없음/void 반환으로 변경; onMutate에서 HAS_UNREAD 캐시를 false로 세팅하고, 성공 시 HAS_UNREAD 무효화 유지.
매칭 수신 플로우 조정
src/pages/result/components/matching-receive-view.tsx
수락 처리에서 개별 알림 읽기 호출 제거. accept 성공 시 라벨별로 SINGLE·GROUP 매치 상태 쿼리 모두 무효화. 성공 후 isGroupMatching에 따라 그룹 경로 또는 1:1 성공 경로로 분기. 오류 시 기존대로 ERROR 경로로 이동.
하단 내비게이션에서 배지 제거 트리거
src/shared/components/bottom-navigation/bottom-navigation.tsx
React Query useMutation으로 READ_ALL_ALARMS 호출 추가. MATCH 탭 클릭 시 HAS_UNREAD가 true면 readAllAlarmsMutation.mutate() 실행 후 내비게이션 진행. 기존 네비게이션 로직은 유지.

Sequence Diagram(s)

sequenceDiagram
  participant U as 사용자
  participant Nav as BottomNavigation
  participant Q as ReactQuery
  participant API as /v2/users/alarms

  U->>Nav: MATCH 탭 클릭
  Nav->>Q: HAS_UNREAD 조회
  alt 미읽음 존재
    Nav->>Q: mutate(READ_ALL_ALARMS)
    Q->>API: POST /v2/users/alarms
    API-->>Q: 200 OK
    Q-->>Nav: onSuccess (HAS_UNREAD 무효화)
  end
  Nav->>U: MATCH 화면으로 이동
Loading
sequenceDiagram
  participant U as 사용자
  participant View as MatchingReceiveView
  participant Match as AcceptMutation
  participant Q as ReactQuery
  participant Router as Router

  U->>View: 수락 클릭
  View->>Match: mutate(accept)
  alt 성공
    View->>Q: invalidate MATCH_STATUS (SINGLE, GROUP) for each label
    alt 그룹 매칭
      View->>Router: 그룹 경로로 이동
    else 1:1 매칭
      View->>Router: 1:1 성공 경로로 이동
    end
  else 실패
    View->>Router: ERROR 경로로 이동
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
알림배지 제거 API 연결 (#378)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
수락 플로우에서 알림 읽기 호출 제거 및 내비게이션/캐시 무효화 범위 변경 (src/pages/result/components/matching-receive-view.tsx) 이슈는 알림 배지 제거 API 연결에 한정되어 있으나, 매칭 수락 후의 내비게이션 분기 및 MATCH_STATUS(SINGLE/GROUP) 동시 무효화는 배지 API 연동 목적 범위를 벗어나는 별도 동작 변경입니다.
MATCH 탭 이동 시 전체 알림 읽음 트리거 추가 외의 네비게이션 로직 유지/변경 (src/shared/components/bottom-navigation/bottom-navigation.tsx) 배지 제거 API 호출은 관련 있으나, 탭 진입 타이밍에서의 부수 동작(예: 동기화 시점, 네비게이션 우선순위)은 이슈에 명시되지 않아 추가 정책 변경으로 보입니다.

Possibly related PRs

Suggested reviewers

  • heesunee
  • Dubabbi
  • yeeeww

Poem

토끼가 폴짝, 배지를 훌쩍 털었네 🐰
한 번에 쓱—모두 읽음으로 바꿨네 📭
MATCH로 폴짝, 길이 열리고
그룹이든 1:1이든 제자리로 고고!
오늘도 인박스는 반짝 맑음 ✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#378/read-alarms

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Sep 7, 2025

MATEBALL-STORYBOOK
⚾ Storybook 배포가 완료되었습니다!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/shared/constants/api.ts (1)

51-52: POST_READ_ALARM 상수 제거 검토 요청

src/shared/constants/api.ts 50번째 줄에 정의된 POST_READ_ALARM이 코드베이스 내 다른 참조 없이 선언만 남아 있습니다. 전체 읽음 엔드포인트로 대체되었으므로 혼선 방지를 위해 삭제를 권장합니다.

src/pages/result/components/matching-receive-view.tsx (1)

63-67: 그룹 수락 후 MATCH 화면으로 이동 시 배지 미제거 가능성

배지 제거가 바텀 탭 클릭에만 묶여 있어(하단 네비게이션 onClick) 수락 성공 후 프로그래매틱 네비게이션으로 MATCH로 이동하면 배지가 남을 수 있습니다. MATCH 화면 진입 시점(useEffect)에서 일괄로 readAll을 트리거하도록 중앙집중화하는 편이 UX 일관성에 좋습니다.

추가 제안(매치 화면 컨테이너 예시):

// MatchPage.tsx (예시)
const { data: hasUnread } = useQuery(alarmQueries.HAS_UNREAD());
const readAll = useMutation(alarmMutations.READ_ALL_ALARMS());
useEffect(() => {
  if (hasUnread) readAll.mutate();
}, [hasUnread]);
src/shared/components/bottom-navigation/bottom-navigation.tsx (1)

18-31: 중복 호출 가드 및 낙관적 업데이트 고려

탭 연타 시 중복 호출을 피하기 위해 isPending 가드를 추가해 주세요. 배지를 즉시 숨기려면(체감 개선) 낙관적 업데이트는 mutation 옵션(onMutate) 쪽에서 처리하는 것을 권장합니다(별도 코멘트 참고).

-  if (path === ROUTES.MATCH && hasUnreadAlarms) {
-    readAllAlarmsMutation.mutate();
-  }
+  if (path === ROUTES.MATCH && hasUnreadAlarms && !readAllAlarmsMutation.isPending) {
+    readAllAlarmsMutation.mutate();
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 283d55e and faf01ca.

📒 Files selected for processing (5)
  • src/pages/result/components/matching-receive-view.tsx (1 hunks)
  • src/shared/apis/alarm/alarm-mutations.ts (1 hunks)
  • src/shared/components/bottom-navigation/bottom-navigation.tsx (3 hunks)
  • src/shared/constants/api.ts (1 hunks)
  • src/shared/constants/query-key.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/shared/components/bottom-navigation/bottom-navigation.tsx (2)
src/shared/apis/alarm/alarm-mutations.ts (1)
  • alarmMutations (7-16)
src/shared/routes/routes-config.ts (1)
  • ROUTES (1-23)
src/pages/result/components/matching-receive-view.tsx (1)
src/shared/routes/routes-config.ts (1)
  • ROUTES (1-23)
src/shared/apis/alarm/alarm-mutations.ts (3)
src/shared/constants/query-key.ts (1)
  • ALARM_KEY (67-70)
src/shared/apis/base/http.ts (1)
  • post (7-9)
src/shared/constants/api.ts (1)
  • END_POINT (3-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: chromatic
🔇 Additional comments (1)
src/shared/constants/query-key.ts (1)

68-70: 잔여 ALARM_KEY.READ 참조 없음 확인
ALARM_KEY.READ 호출이 코드베이스에서 발견되지 않아 READ → READ_ALL 전환이 완료되었습니다.

@cloudflare-workers-and-pages
Copy link

Deploying mateball-client with  Cloudflare Pages  Cloudflare Pages

Latest commit: cf1e359
Status: ✅  Deploy successful!
Preview URL: https://37fd082d.mateball-client.pages.dev
Branch Preview URL: https://feat--378-read-alarms.mateball-client.pages.dev

View logs

@heesunee heesunee merged commit f7ca6a0 into develop Sep 7, 2025
6 of 7 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between faf01ca and cf1e359.

📒 Files selected for processing (1)
  • src/shared/apis/alarm/alarm-mutations.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/shared/apis/alarm/alarm-mutations.ts (3)
src/shared/constants/query-key.ts (1)
  • ALARM_KEY (67-70)
src/shared/apis/base/http.ts (1)
  • post (7-9)
src/shared/constants/api.ts (1)
  • END_POINT (3-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: chromatic
🔇 Additional comments (2)
src/shared/apis/alarm/alarm-mutations.ts (2)

9-12: 제네릭·엔드포인트 교체 적절

mutationOptions 제네릭 순서, post의 반환 제네릭, READ_ALL 키/엔드포인트 적용 모두 적절합니다.


15-17: 연관 쿼리 추가 무효화 불필요
alarm-queries.ts에 정의된 쿼리는 HAS_UNREAD 하나뿐이므로, 현재 invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD })만으로 충분합니다.

Comment on lines +12 to 17
onMutate: async () => {
queryClient.setQueryData(ALARM_KEY.HAS_UNREAD, false);
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

낙관적 업데이트 롤백 누락 → 실패 시 배지가 계속 숨겨질 수 있음

API 실패해도 HAS_UNREAD를 false로 유지합니다. 이전 값 스냅샷 저장 → onError 롤백, 무조건 onSettled에서 invalidate 하도록 바꿔주세요. 컨텍스트 타입 제네릭(4번째)도 명시 필요.

-  READ_ALL_ALARMS: () =>
-    mutationOptions<void, Error, void>({
+  READ_ALL_ALARMS: () =>
+    mutationOptions<void, Error, void, { previous?: boolean }>({
       mutationKey: ALARM_KEY.READ_ALL(),
       mutationFn: () => post<void>(END_POINT.POST_READ_ALL_ALARMS),
-      onMutate: async () => {
-        queryClient.setQueryData(ALARM_KEY.HAS_UNREAD, false);
-      },
-      onSuccess: () => {
-        queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
-      },
+      onMutate: async () => {
+        await queryClient.cancelQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
+        const previous = queryClient.getQueryData<boolean>(ALARM_KEY.HAS_UNREAD);
+        queryClient.setQueryData<boolean>(ALARM_KEY.HAS_UNREAD, false);
+        return { previous };
+      },
+      onError: (_err, _vars, ctx) => {
+        if (ctx?.previous !== undefined) {
+          queryClient.setQueryData(ALARM_KEY.HAS_UNREAD, ctx.previous);
+        }
+      },
+      onSettled: () => {
+        queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
+      },
     }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onMutate: async () => {
queryClient.setQueryData(ALARM_KEY.HAS_UNREAD, false);
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
},
export const alarmMutations = {
READ_ALL_ALARMS: () =>
mutationOptions<void, Error, void, { previous?: boolean }>({
mutationKey: ALARM_KEY.READ_ALL(),
mutationFn: () => post<void>(END_POINT.POST_READ_ALL_ALARMS),
// Snapshot and clear unread flag optimistically
onMutate: async () => {
await queryClient.cancelQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
const previous = queryClient.getQueryData<boolean>(ALARM_KEY.HAS_UNREAD);
queryClient.setQueryData<boolean>(ALARM_KEY.HAS_UNREAD, false);
return { previous };
},
// Roll back if the mutation fails
onError: (_err, _vars, ctx) => {
if (ctx?.previous !== undefined) {
queryClient.setQueryData(ALARM_KEY.HAS_UNREAD, ctx.previous);
}
},
// Always re-fetch after either success or error
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD });
},
}),
// …other mutations
};
🤖 Prompt for AI Agents
In src/shared/apis/alarm/alarm-mutations.ts around lines 12 to 17, the
optimistic update currently sets HAS_UNREAD to false without saving a snapshot
or rolling back on failure and only invalidates onSuccess; change onMutate to
capture and return the previous value snapshot (as the mutation context),
annotate the useMutation call with the four generics including the context type,
implement onError to restore the previous value from context (rollback), and
move the queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD }) into
onSettled so the cache is always refreshed after success or failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat new feature 채은

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 알림배지 제거 api를 연결합니다.

2 participants