✨ [Feature] 알림 목록 화면 구현 및 API 연동 (#57)#58
Conversation
📝 WalkthroughWalkthrough이 PR은 알림 목록 조회 및 읽음 처리 API, 재사용 가능한 필터 바 및 메뉴 버튼 컴포넌트, 알림 목록 화면 구현, 캘린더/홈 화면 통합, 그리고 스타일/다국어 지원을 추가합니다. Changes알림 목록 기능 및 UI 통합
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant Home as HomeScreen
participant Notifications as NotificationsScreen
participant API as src/api/notifications.ts
participant Server as Backend API
User->>Home: 알림 벨 버튼 탭
Home->>Notifications: router.push('/notifications')
Notifications->>API: fetchNotifications({ size: 20 })
API->>Server: GET /api/v1/notifications
Server-->>API: { result, cursor, hasNext }
API-->>Notifications: NotificationsResult
Notifications->>Notifications: 자녀 필터 적용 후 날짜별 그룹화
Notifications-->>User: 알림 목록 렌더링
User->>Notifications: 알림 항목 클릭
Notifications->>API: markNotificationRead(notificationId)
API->>Server: PATCH /api/v1/notifications/{id}/read
Server-->>API: { readCount }
Notifications->>Notifications: 낙관적 UI 업데이트 (읽음 상태)
User->>Notifications: 메뉴 > "전체 읽음" 선택
Notifications->>API: markAllNotificationsRead()
API->>Server: PATCH /api/v1/notifications/read-all
Server-->>API: { readCount }
Notifications->>Notifications: 모든 항목을 읽음으로 변경
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
app/profile/notification.tsx (1)
41-42: ⚡ Quick win테마 색상은 상수 팔레트로 통일해 주세요.
Line 41-42가 하드코딩 색상이라 팔레트 변경 시 이 화면만 누락될 위험이 있습니다.
colors.pink를 사용해 일관성을 맞추는 게 안전합니다.diff 제안
- iconColor: '`#F9A0A0`', - iconBg: '`#FCEBEB`', + iconColor: colors.pink[300], + iconBg: colors.pink[100],🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/profile/notification.tsx` around lines 41 - 42, Replace the hardcoded hex values for iconColor and iconBg in app/profile/notification.tsx with the theme palette entries (e.g., use colors.pink for the foreground and a lighter shade like colors.pink[50] or colors.pink[100] for the background) so the component follows the shared color constants; update the import to use the shared colors palette if not already imported and change the object properties iconColor and iconBg to reference colors.pink entries instead of '`#F9A0A0`' and '`#FCEBEB`'.app/notifications/index.tsx (1)
53-63: ⚡ Quick win초기 로딩 실패가 무시되어 빈 화면으로 고정됩니다.
.catch(() => {})로 오류를 삼키면fetchNotifications/fetchChildren실패 시에도ListEmptyComponent의 "알림 없음"만 표시되어, 사용자가 네트워크 오류와 실제 빈 상태를 구분하거나 재시도할 수 없습니다. 오류 상태를 별도로 두고 재시도 UI를 노출하는 것을 권장합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/notifications/index.tsx` around lines 53 - 63, The current useEffect swallows errors with .catch(() => {}), causing network failures to show the same "no notifications" UI; update the effect to track an error state (e.g., add setLoadError or setFetchError via useState) and in the Promise.catch handler set that error state (pass the caught error or a boolean), so the component can render an error/retry UI instead of ListEmptyComponent; keep the finally handler to setIsLoading(false). Also expose a retry handler (e.g., refetchNotifications that calls fetchNotifications/fetchChildren and resets setLoadError) and wire it to the retry button in the component rendering logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/notifications/index.tsx`:
- Around line 80-96: The updater functions markAsRead and handleMarkAllRead
currently call markNotificationRead(id) and markAllNotificationsRead() inside
the setNotifications updater, which can cause duplicate network requests in
React 19 strict mode; change them to only perform a pure optimistic state update
inside setNotifications (use the updater to return the new notifications with
read: true) and then call the API after the state update (outside the updater),
handling failures by rolling back via a separate setNotifications call that
reverses the optimistic change; update markAsRead to compute the target/read
check before calling setNotifications, call markNotificationRead(id).catch(() =>
rollback), and update handleMarkAllRead to set all read optimistically then call
markAllNotificationsRead().catch(() => rollback). Also replace the useEffect
.catch(()=>{}) with an explicit error state or retry UI instead of swallowing
errors.
---
Nitpick comments:
In `@app/notifications/index.tsx`:
- Around line 53-63: The current useEffect swallows errors with .catch(() =>
{}), causing network failures to show the same "no notifications" UI; update the
effect to track an error state (e.g., add setLoadError or setFetchError via
useState) and in the Promise.catch handler set that error state (pass the caught
error or a boolean), so the component can render an error/retry UI instead of
ListEmptyComponent; keep the finally handler to setIsLoading(false). Also expose
a retry handler (e.g., refetchNotifications that calls
fetchNotifications/fetchChildren and resets setLoadError) and wire it to the
retry button in the component rendering logic.
In `@app/profile/notification.tsx`:
- Around line 41-42: Replace the hardcoded hex values for iconColor and iconBg
in app/profile/notification.tsx with the theme palette entries (e.g., use
colors.pink for the foreground and a lighter shade like colors.pink[50] or
colors.pink[100] for the background) so the component follows the shared color
constants; update the import to use the shared colors palette if not already
imported and change the object properties iconColor and iconBg to reference
colors.pink entries instead of '`#F9A0A0`' and '`#FCEBEB`'.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 48f7f117-acb3-44c2-a536-ca35d98bbed8
📒 Files selected for processing (14)
app/(tabs)/calendar.tsxapp/(tabs)/index.tsxapp/notifications/index.tsxapp/profile/notification.tsxsrc/api/notifications.tssrc/components/common/ChildFilterBar.tsxsrc/components/common/Header.tsxsrc/components/common/HeaderMenuButton.tsxsrc/constants/colors.tssrc/i18n/locales/en.jsonsrc/i18n/locales/ko.jsonsrc/styles/calendar/calendar.tssrc/styles/notifications/notifications.tssrc/styles/profile/profileNotification.ts
📜 Review details
🔇 Additional comments (13)
app/profile/notification.tsx (1)
48-48: LGTM!Also applies to: 55-55, 62-62, 155-155
src/constants/colors.ts (1)
19-22: LGTM!src/i18n/locales/en.json (1)
612-613: LGTM!Also applies to: 618-630
src/i18n/locales/ko.json (1)
618-630: LGTM!src/styles/calendar/calendar.ts (1)
13-16: LGTM!src/styles/notifications/notifications.ts (1)
1-113: LGTM!src/styles/profile/profileNotification.ts (1)
110-115: LGTM!Also applies to: 132-132, 138-138
src/api/notifications.ts (1)
1-138: LGTM!src/components/common/ChildFilterBar.tsx (1)
19-105: LGTM!src/components/common/HeaderMenuButton.tsx (1)
18-117: LGTM!src/components/common/Header.tsx (1)
13-49: LGTM!app/(tabs)/index.tsx (1)
17-56: LGTM!app/(tabs)/calendar.tsx (1)
62-70: ⚡ Quick win
payload.targetDate가YYYY-MM-DD형식인지 확인 필요
app/(tabs)/calendar.tsx에서 알림의item.payload.targetDate를 그대로selectedDate로 두고(또한dateParam.split('-')로 월/년을 숫자 파싱)formatDayLabel/MonthCalendar비교에 그대로 사용합니다.
src/api/notifications.ts의payload.targetDate는Record<string, string | undefined>로만 타입이 잡혀 있어 포맷 보장이 없고,YYYY-MM, ISO datetime(YYYY-MM-DDTHH:mm...), zero-padding 누락(2026-5-7)이면 day 파싱(map(Number))이 깨지거나 선택 표시가 누락될 수 있습니다.
백엔드에서targetDate가 시간 없이YYYY-MM-DD(월/일 2자리, zero-padding 포함) 으로 내려오는지 확인해 주세요.
📌 작업 내용
GET /api/v1/notificationsPATCH /api/v1/notifications/{notificationId}/readPATCH /api/v1/notifications/read-all📷 스크린 샷
🔗 관련 이슈
Closes #57
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선