Skip to content

✨ [Feature] 알림 목록 화면 구현 및 API 연동 (#57)#58

Merged
hyeeon merged 3 commits into
developfrom
feat/notification
May 31, 2026
Merged

✨ [Feature] 알림 목록 화면 구현 및 API 연동 (#57)#58
hyeeon merged 3 commits into
developfrom
feat/notification

Conversation

@hyeeon

@hyeeon hyeeon commented May 31, 2026

Copy link
Copy Markdown
Collaborator

📌 작업 내용

  • 알림 목록 UI 구현
  • 알림 목록 조회 GET /api/v1/notifications
  • 단건 읽음 처리 PATCH /api/v1/notifications/{notificationId}/read
  • 전체 읽음 처리 PATCH /api/v1/notifications/read-all
  • 헤더, 필터바 컴포넌트 분리

📷 스크린 샷

⚠️ 참고 사항

🔗 관련 이슈

Closes #57

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 알림 화면 및 알림 관리 기능 추가
    • 홈 화면에 알림 벨 버튼 추가
    • 자녀별 알림 필터링 기능 추가
  • 개선

    • 달력 화면 네비게이션 및 헤더 UI 개선
    • 다국어 지원 강화 (영어, 한국어)
    • 알림 화면 시간 표시 및 날짜 그룹화 기능 추가

@hyeeon
hyeeon requested a review from chae1125 May 31, 2026 17:49
@hyeeon hyeeon self-assigned this May 31, 2026
@hyeeon hyeeon added the feat New feature label May 31, 2026
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

이 PR은 알림 목록 조회 및 읽음 처리 API, 재사용 가능한 필터 바 및 메뉴 버튼 컴포넌트, 알림 목록 화면 구현, 캘린더/홈 화면 통합, 그리고 스타일/다국어 지원을 추가합니다.

Changes

알림 목록 기능 및 UI 통합

Layer / File(s) Summary
알림 API 계층
src/api/notifications.ts
NotificationApiError, getAuthHeader, 알림 조회/읽음 처리/푸시 토큰 등록 함수와 공개 타입/인터페이스(NotificationType, NotificationApiItem, NotificationsResult, FetchNotificationsParams, RegisterPushTokenParams, PushTokenResult)를 정의하여 REST API 호출을 캡슐화.
재사용 가능한 UI 컴포넌트
src/components/common/ChildFilterBar.tsx, src/components/common/HeaderMenuButton.tsx, src/components/common/Header.tsx
ChildFilterBar는 자녀 항목과 "전체" 옵션을 가로 스크롤 필터로 렌더링하고, HeaderMenuButton은 Ionicons 버튼 클릭 시 동적으로 위치한 드롭다운 메뉴를 표시하며, Header는 새로운 선택적 rightComponent prop으로 우측 영역 커스텀 렌더링을 지원.
알림 목록 화면 구현
app/notifications/index.tsx
초기 마운트 시 fetchNotificationsfetchChildren 병렬 호출, 무한 스크롤 시 커서 기반 추가 로딩, 개별/전체 읽음 처리 시 낙관적 UI 업데이트(실패 시 되돌림), 자녀 필터 적용 후 생성 시각 기준 날짜 그룹화, 그리고 타입별 라우팅 분기를 구현하는 완전한 알림 목록 화면.
캘린더 및 홈 화면 통합
app/(tabs)/calendar.tsx, app/(tabs)/index.tsx
캘린더 화면은 date 네비게이션 파라미터 처리 및 Header/ChildFilterBar 컴포넌트 적용, 홈 화면은 getGreetingByTime 함수에 언어 인자 추가 및 알림 버튼에 /notifications 네비게이션 동작 추가.
지원 변경: 스타일, 다국어, 색상
src/styles/notifications/notifications.ts, src/styles/calendar/calendar.ts, src/styles/profile/profileNotification.ts, src/i18n/locales/en.json, src/i18n/locales/ko.json, src/constants/colors.ts, app/profile/notification.tsx
알림 화면 스타일 추가, 캘린더 헤더 스타일 리팩토링 및 필터 스타일 제거, 프로필 알림 설정 아이템 레이아웃/텍스트 조정, 영문/한국어 i18n 다국어 문자열(notifications 섹션) 및 핑크 색상 팔레트 추가, 프로필 알림 아이콘 색상 및 크기 업데이트.

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: 모든 항목을 읽음으로 변경
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • GACHI-Project/GACHI-FE#36: 캘린더 화면의 주간/월간 모드 네비게이션 및 상단 UI 구성과 직접 연결되는 선행 작업.
  • GACHI-Project/GACHI-FE#40: Header 컴포넌트의 rightComponent prop 추가를 직접 활용하여 캘린더 우측 토글 아이콘 커스터마이징.
  • GACHI-Project/GACHI-FE#18: 홈 화면 인사 생성 다국어 처리 및 알림 버튼 네비게이션 기능과 직접 관련.

Suggested reviewers

  • chae1125

Poem

🐰 알림의 숲을 거닐며
API와 컴포넌트 손을 맞잡고
필터 바는 노래하고, 메뉴는 춤을 춘다
읽음의 낙관이 화면을 밝히고
다국어 번역이 세상을 더 넓혀주네 ✨

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed 모든 링크된 이슈 #57의 요구사항이 충족되었습니다: 알림 목록 UI 구현 [#57], GET 알림 목록 조회 API [#57], PATCH 단건 읽음 [#57], PATCH 전체 읽음 [#57]이 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed 일부 관련 리팩토링이 포함되었습니다: Header와 ChildFilterBar 컴포넌트 분리, 캘린더 화면 네비게이션 처리, 색상 팔레트 확장이 알림 화면 구현을 지원하는 범위 내입니다.
Title check ✅ Passed PR 제목은 알림 목록 화면 구현 및 API 연동이라는 핵심 변경 사항을 명확하게 설명하며, 변경 사항 전체를 잘 대표합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/notification

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (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

📥 Commits

Reviewing files that changed from the base of the PR and between 88777dd and aa9175a.

📒 Files selected for processing (14)
  • app/(tabs)/calendar.tsx
  • app/(tabs)/index.tsx
  • app/notifications/index.tsx
  • app/profile/notification.tsx
  • src/api/notifications.ts
  • src/components/common/ChildFilterBar.tsx
  • src/components/common/Header.tsx
  • src/components/common/HeaderMenuButton.tsx
  • src/constants/colors.ts
  • src/i18n/locales/en.json
  • src/i18n/locales/ko.json
  • src/styles/calendar/calendar.ts
  • src/styles/notifications/notifications.ts
  • src/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.targetDateYYYY-MM-DD 형식인지 확인 필요

app/(tabs)/calendar.tsx에서 알림의 item.payload.targetDate를 그대로 selectedDate로 두고(또한 dateParam.split('-')로 월/년을 숫자 파싱) formatDayLabel/MonthCalendar 비교에 그대로 사용합니다.
src/api/notifications.tspayload.targetDateRecord<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 포함) 으로 내려오는지 확인해 주세요.

Comment thread app/notifications/index.tsx

@chae1125 chae1125 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

와~ 알림~~ 수고하셨습니다

@hyeeon hyeeon changed the title ✨ [Feature] 알림 목록 화면 구현 및 API 연동 ✨ [Feature] 알림 목록 화면 구현 및 API 연동 (#57) May 31, 2026
@hyeeon
hyeeon merged commit 872dde1 into develop May 31, 2026
1 check passed
@hyeeon
hyeeon deleted the feat/notification branch May 31, 2026 18:20
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.

✨ [Feature] 알림 목록 구현 및 API 연동

2 participants