Skip to content

[Feature/#227] 리포트 화면 구현 - #229

Merged
l5x5l merged 20 commits into
developfrom
feature/#227-report-summary
Aug 3, 2026
Merged

[Feature/#227] 리포트 화면 구현#229
l5x5l merged 20 commits into
developfrom
feature/#227-report-summary

Conversation

@l5x5l

@l5x5l l5x5l commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

[ PR Content ]

리포트 화면을 구현합니다.

Related issue

Screenshot 📸

KakaoTalk_Video_2026-07-31-20-19-06.mp4

감정 구슬 선택 화면 전/후 비교

Work Description

  • 리포트 화면 구현
  • 감정 구슬 선택 화면 세부 UI 수정

To Reviewers 📢

  • 리포트 화면에서 달력 데이터의 경우 앞뒤 1개의 월 데이터를 같이 로드하는 구조입니다!
  • 감정구슬 데이터 자체가 등록 당일을 제외하면 변경될 수 없는 구조이기 때문에, 캐싱 로직을 추가함으로써 불필요하게 API를 호출하는 것을 피하고자 했습니다!
  • 테스트 도중 감정 구슬을 선택하는 화면에 대해 일부 화면 크기에서 글자와 감정 구슬이 겹쳐 보이는 문제가 발견되어 살짝 크기 및 간격을 조정했습니다!
  • 추가적인 의견이나 궁금한 점 있으시면 코멘트 부탁드립니다!

Summary by CodeRabbit

  • 새로운 기능

    • 월별 감정 기록과 배지를 확인할 수 있는 ‘리포트’ 탭을 추가했습니다.
    • 감정 기록을 달력에서 확인하고, 날짜를 선택해 상세 내용을 볼 수 있습니다.
    • 월별 배지 현황과 획득 상태를 확인할 수 있습니다.
    • 이전·다음 달 이동 및 청년 정책 화면 바로가기를 지원합니다.
  • 개선

    • 감정 선택 화면의 기기별 레이아웃과 조작감을 개선했습니다.
    • 감정 등록 후 리포트 내용이 최신 상태로 갱신됩니다.

l5x5l added 16 commits July 13, 2026 21:15
: 당일 감정구슬 조회 바텀시트, 이전/이후 월로 이동
@l5x5l l5x5l self-assigned this Jul 31, 2026
@l5x5l l5x5l added ✨ Feature 새로운 기능 구현 세환 labels Jul 31, 2026
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b428d8bd-84b1-4a45-af51-b0414863126e

📥 Commits

Reviewing files that changed from the base of the PR and between f22d5cc and 5ce0978.

📒 Files selected for processing (1)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/emotiondaybottomsheet/EmotionDayBottomSheet.kt

Walkthrough

활동 로그 조회와 월별 캐시를 추가했습니다. 배지와 감정 구슬을 표시하는 리포트 화면을 구현했습니다. 리포트 탭과 홈 내비게이션을 연결했습니다. 감정 등록 성공 시 현재 월의 감정 구슬 캐시를 무효화합니다.

Changes

활동 로그 리포트

Layer / File(s) Summary
활동 로그 계약과 변환
domain/src/main/java/com/threegap/bitnagil/domain/activitylog/..., data/src/main/java/com/threegap/bitnagil/data/activitylog/model/..., data/src/main/java/com/threegap/bitnagil/data/activitylog/service/..., data/src/main/java/com/threegap/bitnagil/data/activitylog/datasource/...
배지와 감정 구슬 도메인 모델, 저장소·데이터 소스 계약, Retrofit 응답 모델과 변환을 추가했습니다.
활동 로그 캐시와 의존성 연결
data/src/main/java/com/threegap/bitnagil/data/activitylog/datasourceImpl/..., data/src/main/java/com/threegap/bitnagil/data/activitylog/repositoryImpl/..., app/src/main/java/com/threegap/bitnagil/di/data/..., domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt
월별 메모리 캐시와 Mutex 기반 조회를 추가했습니다. 감정 등록 성공 시 캐시를 삭제합니다. Hilt가 서비스, 데이터 소스, 저장소를 연결합니다.
리포트 상태와 UI 모델
presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/contract/SummaryState.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/..., presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryViewModel.kt
월별 데이터, 선택 날짜, 로딩 상태를 관리하는 상태와 UI 모델을 추가했습니다. 인접 3개월 데이터를 병렬로 요청합니다.
리포트 화면 UI
presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryScreen.kt, presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/...
월별 배지, 6주 달력, 감정 상세 바텀시트, 월 이동과 페이지 기반 전환을 구현했습니다.
홈 연결과 감정 화면 조정
app/src/main/java/com/threegap/bitnagil/navigation/home/..., app/src/main/res/drawable/ic_report.xml, core/designsystem/src/main/res/drawable/ic_badge_question.xml, presentation/src/main/java/com/threegap/bitnagil/presentation/screen/emotion/...
리포트 탭과 HomeRoute.Summary를 추가했습니다. 리포트 및 기본 배지 아이콘을 추가했습니다. 감정 선택 화면의 크기와 상태 계산 기준을 변경했습니다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant 사용자
  participant SummaryScreen
  participant SummaryViewModel
  participant GetBadgesUseCase
  participant ActivityLogRepositoryImpl
  participant ActivityLogService

  사용자->>SummaryScreen: 리포트 탭 선택
  SummaryScreen->>SummaryViewModel: 월 변경 전달
  SummaryViewModel->>GetBadgesUseCase: 인접 월 조회
  GetBadgesUseCase->>ActivityLogRepositoryImpl: YearMonth 전달
  ActivityLogRepositoryImpl->>ActivityLogService: 배지 API 호출
  ActivityLogService-->>ActivityLogRepositoryImpl: 배지 응답 반환
  ActivityLogRepositoryImpl-->>SummaryViewModel: MonthlyBadge 결과 반환
  SummaryViewModel-->>SummaryScreen: 상태 갱신
Loading

Suggested reviewers: wjdrjs00

Poem

나는 작은 토끼, 리포트 탭을 깡충
배지와 구슬을 달력에 쏙쏙
캐시는 월별로 차곡차곡
새 기록엔 해당 달을 비우고
아이콘은 반짝반짝!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 리포트 화면 구현이라는 주요 변경 사항을 명확하고 간결하게 설명합니다.
Description check ✅ Passed 관련 이슈, 스크린샷, 작업 내용, 리뷰어 확인 사항을 모두 포함합니다.
Linked Issues check ✅ Passed 리포트 화면을 구현하고 네비게이션에 Summary 경로를 추가하여 이슈 #227의 요구 사항을 충족합니다.
Out of Scope Changes check ✅ Passed 변경 사항은 리포트 화면, 네비게이션, 데이터 처리 및 명시된 감정 선택 UI 수정 범위에 포함됩니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#227-report-summary

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.

@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: 7

🧹 Nitpick comments (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryScreen.kt (1)

64-84: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

currentPage 대신 settledPage를 사용하십시오.

LaunchedEffect(pagerState.currentPage)는 페이지가 스냅 위치에 가까워지는 즉시 갱신되는 currentPage를 감지합니다. 공식 문서에 따르면 currentPage는 스크롤 중에도 즉시 갱신되지만, settledPage는 애니메이션이 완전히 끝날 때까지 값이 유지됩니다.

사용자가 여러 달을 빠르게 스와이프하면, 최종적으로 머무르지 않는 중간 달에 대해서도 onMonthChanged가 호출됩니다. 이는 불필요한 뱃지/감정 구슬 프리페치 호출과 월 라벨 텍스트의 깜빡임을 유발합니다.

pagerState.settledPage로 바꾸면 스크롤이 완전히 멈춘 뒤에만 상태를 갱신합니다.

♻️ 제안하는 수정
-    LaunchedEffect(pagerState.currentPage) {
-        val monthOffset = pagerState.currentPage - INITIAL_PAGE
+    LaunchedEffect(pagerState.settledPage) {
+        val monthOffset = pagerState.settledPage - INITIAL_PAGE
         val targetMonth = YearMonth.now().plusMonths(monthOffset.toLong())
         if (state.currentMonth != targetMonth) {
             onMonthChanged(targetMonth)
         }
     }

Based learnings from Android Developers 공식 문서: "currentPage immediately updates if the page is close enough to the snap position, but settledPage remains the same until all the animations are finished running."

🤖 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
`@presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryScreen.kt`
around lines 64 - 84, SummaryScreen의 페이지 변경 감지에서 LaunchedEffect와 월 오프셋 계산에 사용하는
pagerState.currentPage를 pagerState.settledPage로 변경하십시오. 애니메이션이 완전히 종료된 최종 페이지만
기준으로 onMonthChanged가 호출되도록 하고, 나머지 월 계산 및 상태 비교 로직은 유지하십시오.
🤖 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
`@data/src/main/java/com/threegap/bitnagil/data/activitylog/model/response/BadgeResponse.kt`:
- Around line 44-45: Update String.toBadgeType in BadgeResponse to stop falling
back to BadgeType.UNKNOWN and instead propagate a
serializationException/SerializationException when BadgeType.valueOf receives an
unsupported server value; remove the BadgeType.UNKNOWN fallback comment. In
BadgeType.kt, make no direct change unless required to support this
exception-based mapping.

In
`@data/src/main/java/com/threegap/bitnagil/data/activitylog/repositoryImpl/ActivityLogRepositoryImpl.kt`:
- Around line 61-62: Synchronize invalidateEmotionMarbleCache with in-flight
emotion-marble reads using emotionMarbleFetchMutex, ensuring cache removal
cannot race with a fetch that later stores stale data. Alternatively, track
per-month generations and prevent reads started before invalidation from writing
their results.
- Around line 40-58: Update getEmotionMarbles so the cache key includes both
startDate and endDate, preventing results for one date range from being reused
for another; alternatively, change the repository contract to accept YearMonth
and consistently calculate the month boundaries internally if only monthly
queries are supported. Update the corresponding emotionMarblesByMonth cache
lookups and saveEmotionMarbles calls to use the selected range key or normalized
monthly range.

In
`@presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/summarybadge/SummaryBadgeView.kt`:
- Line 1: SummaryBadgeView와 SummaryScreen의 높이 설정을 일치시키십시오. StarImage의 offset 계산이
260.dp 기준이라면 SummaryScreen에서 전달하는 .height(360.dp)를 260.dp로 변경하고, 360.dp가 의도된
값이라면 Background 내부 높이와 모든 star/offset 배치를 360.dp 기준으로 갱신하십시오.
- Around line 86-97: Align the height configuration between SummaryBadgeView()
and its SummaryScreen.kt caller: use one consistent rendering height instead of
combining the caller’s 360.dp with the internal 260.dp constraint in the
Background/BoxWithConstraints block. Preserve the StarImage offset and alignment
design by either matching the caller to 260.dp or removing the internal fixed
height and related statusBarsPadding so the component uses the caller-provided
size.

In
`@presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/summarycalendar/SummaryCalendarView.kt`:
- Around line 139-146: Update the SummaryCalendarView preview data to use
prevMonth.atEndOfMonth() instead of prevMonth.atDay(30), ensuring the previous
month’s final valid date is used for every month, including February.

In
`@presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryViewModel.kt`:
- Around line 66-110: SummaryViewModel에서 배지 및 감정 구슬 요청 실패가 로그에만 남지 않고 UI에 전달되도록
수정하세요. SummaryState에 오류 상태 필드를 추가해 실패 정보를 반영하거나, container의 Unit 타입을 실제 오류 사이드
이펙트 타입으로 변경하고 fetchBadges와 fetchEmotionMarbles의 onFailure에서 postSideEffect를
호출하세요. 기존 loadingCount 감소 처리는 유지하고 두 요청 경로가 동일한 실패 전달 방식을 사용하도록 하세요.

---

Nitpick comments:
In
`@presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryScreen.kt`:
- Around line 64-84: SummaryScreen의 페이지 변경 감지에서 LaunchedEffect와 월 오프셋 계산에 사용하는
pagerState.currentPage를 pagerState.settledPage로 변경하십시오. 애니메이션이 완전히 종료된 최종 페이지만
기준으로 onMonthChanged가 호출되도록 하고, 나머지 월 계산 및 상태 비교 로직은 유지하십시오.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 47667ab0-1f34-4ba1-8e55-b139221621ed

📥 Commits

Reviewing files that changed from the base of the PR and between d70c57c and 308bd8a.

📒 Files selected for processing (39)
  • app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt
  • app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt
  • app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt
  • app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt
  • app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt
  • app/src/main/java/com/threegap/bitnagil/navigation/home/HomeRoute.kt
  • app/src/main/res/drawable/ic_report.xml
  • core/designsystem/src/main/res/drawable/ic_badge_question.xml
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/datasource/ActivityLogLocalDataSource.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/datasource/ActivityLogRemoteDataSource.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/datasourceImpl/ActivityLogLocalDataSourceImpl.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/datasourceImpl/ActivityLogRemoteDataSourceImpl.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/model/response/BadgeResponse.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/model/response/EmotionMarbleResponse.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/repositoryImpl/ActivityLogRepositoryImpl.kt
  • data/src/main/java/com/threegap/bitnagil/data/activitylog/service/ActivityLogService.kt
  • data/src/main/java/com/threegap/bitnagil/data/emotion/repositoryImpl/EmotionRepositoryImpl.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/model/Badge.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/model/BadgeType.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/model/EmotionMarble.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/model/MonthlyBadge.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/repository/ActivityLogRepository.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/usecase/GetBadgesUseCase.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/activitylog/usecase/GetEmotionMarblesUseCase.kt
  • domain/src/main/java/com/threegap/bitnagil/domain/emotion/usecase/RegisterEmotionUseCase.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/emotion/EmotionScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/emotion/component/template/SwipeEmotionSelectionScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/SummaryViewModel.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/emotiondaybottomsheet/EmotionDayBottomSheet.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/summarybadge/SummaryBadgeView.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/component/template/summarycalendar/SummaryCalendarView.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/contract/SummaryState.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/BadgeImage.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/SummaryBadgeTypeUiModel.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/SummaryBadgeUiModel.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/SummaryEmotionCellUiModel.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/SummaryEmotionDayUiModel.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/screen/summary/model/SummaryEmotionType.kt

@l5x5l
l5x5l requested a review from wjdrjs00 August 1, 2026 06:16

@wjdrjs00 wjdrjs00 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

고생하셨숩니다~!

@l5x5l
l5x5l merged commit f2adb24 into develop Aug 3, 2026
2 checks passed
@l5x5l
l5x5l deleted the feature/#227-report-summary branch August 3, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 구현 세환

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 리포트 화면을 구현합니다.

2 participants