Conversation
Walkthrough알림 읽음 처리 방식을 개별(matchId)에서 전체 일괄로 변경하고, 관련 엔드포인트·쿼리키·뮤테이션을 교체했습니다. 매칭 수신 화면에서 수락 플로우는 알림 읽기 호출을 제거하고 내비게이션 분기만 남겼습니다. 하단 내비게이션에서 MATCH 탭 진입 시 미읽음이 있으면 전체 읽음 API를 호출합니다. Changes
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 화면으로 이동
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
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. Comment |
|
MATEBALL-STORYBOOK |
There was a problem hiding this comment.
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
📒 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 전환이 완료되었습니다.
Deploying mateball-client with
|
| 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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 })만으로 충분합니다.
| onMutate: async () => { | ||
| queryClient.setQueryData(ALARM_KEY.HAS_UNREAD, false); | ||
| }, | ||
| onSuccess: () => { | ||
| queryClient.invalidateQueries({ queryKey: ALARM_KEY.HAS_UNREAD }); | ||
| }, |
There was a problem hiding this comment.
🛠️ 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.
| 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.
#️⃣ Related Issue
Closes #378
💎 PR Point
📸 Screenshot
2025-09-08.2.05.53.mov
Summary by CodeRabbit