Skip to content

[FEAT] 알람 설정 시 미션 종류 선택 기능 추가하기#234

Merged
DongChyeon merged 15 commits into
developfrom
feat/#226-alarm-mission-select
Jul 27, 2025
Merged

[FEAT] 알람 설정 시 미션 종류 선택 기능 추가하기#234
DongChyeon merged 15 commits into
developfrom
feat/#226-alarm-mission-select

Conversation

@DongChyeon
Copy link
Copy Markdown
Member

@DongChyeon DongChyeon commented Jul 23, 2025

Related issue 🛠

closed #226

어떤 변경사항이 있었나요?

  • 🐞 BugFix Something isn't working
  • 🎨 Design Markup & styling
  • 📃 Docs Documentation writing and editing (README.md, etc.)
  • ✨ Feature Feature
  • 🔨 Refactor Code refactoring
  • ⚙️ Setting Development environment setup
  • ✅ Test Test related (Junit, etc.)

CheckPoint ✅

PR이 다음 요구 사항을 충족하는지 확인하세요.

  • PR 컨벤션에 맞게 작성했습니다. (필수)
  • merge할 브랜치의 위치를 확인해 주세요(main❌/develop⭕) (필수)
  • Approve된 PR은 assigner가 머지하고, 수정 요청이 온 경우 수정 후 다시 push를 합니다. (필수)
  • BugFix의 경우, 버그의 원인을 파악하였습니다. (선택)

Work Description ✏️

2025-07-23.5.23.16.mov
  • 미션 종류를 선택하는 바텀시트를 구현하고 화면에 연결했습니다.
  • 바텀시트 내부에 있는 단계 정보 등은 상태 호이스팅을 하면 구조가 너무 복잡해질 수 있어, 내부 상태로 관리했습니다.
  • 같은 이유로, 이후에 작업할 다른 바텀시트들도 보여줄 수 있는 횟수나 선택한 횟수와 같은 값은 내부 상태로 처리할 계획입니다.
  • 이는 ViewModel이 지나치게 비대해지는 것을 방지하고, 바텀시트를 닫는 시점에서만 값이 필요하므로 내부에서 관리해도 충분하다고 판단했기 때문입니다.
  • 또한, 미션 화면이 missionCount, missionType 파라미터에 따라 동적으로 작동하도록 개선했습니다.

Uncompleted Tasks 😅

  • Mission 쪽 리팩토링 및 미션 미리보기 연결
  • AlarmAddEdit 바텀시트가 너무 많아서 ModalBottomSheetLayout으로 감싸고 BottomSheetState 분리

To Reviewers 📢

image
(문수님을 위해 준비한 영양만점 도시락.... addition이 많은 건 로티 파일 탓도 있으니 쫄지 마세요)

이번에도 너무 원기옥이 되는 것 같아서 중간에 끊었습니다
지금보니까 현재 BottomSheet 쪽이 구현이 이상하더라고요?? 이슈 따로 파서 리팩토링하려고 합니다.
미션 쪽도 미션 미리보기 만들려고 하면서 보니까 리팩토링 한번 거치고 하는게 좋을 것 같아 우선 여기까지 올렸습니다.

우선 여기서 코드래빗이 리뷰해주는 BottomSheet나 미션 관련은 무시할 생각입니다.

Summary by CodeRabbit

  • 신규 기능

    • 알람 추가/수정 화면에서 미션 설정 기능이 추가되어 미션 유형과 횟수를 선택할 수 있는 바텀시트가 제공됩니다.
    • 알람 미션 바텀시트에 미션 추가, 선택, 상세 설정, 미리보기 및 삭제 기능이 포함되었습니다.
    • 미션 관련 딥링크가 확장되어 미션 유형과 횟수를 포함합니다.
  • UI 개선

    • 미션 선택 및 설정 UI가 개선되어 미션 유형과 횟수를 명확하게 표시합니다.
    • 미션 진행 상황이 통합된 카운터(currentCount)로 표시되어 직관성이 향상되었습니다.
    • 알람 설정 화면에서 미션 설명에 횟수가 추가되어 표시됩니다.
    • 알람 스누즈 바텀시트에서 공통 컴포넌트인 SelectorItems를 사용하도록 개선되었습니다.
    • 새로운 미션 및 삭제 아이콘 벡터 리소스가 추가되었습니다.
  • 버그 수정 및 리팩터링

    • 알람 시간 표시 로직이 24시간제로 단순화되었습니다.
    • 미션 진행 상태 관리가 shakeCount, clickCount에서 currentCount로 통합되어 일관성이 개선되었습니다.
    • 미션 뷰모델이 미션 타입과 횟수를 SavedStateHandle에서 직접 로드하도록 변경되었습니다.
    • 미션 관련 상태 및 UI 로직이 단순화되고 통합되었습니다.
    • 알람 푸시 알림 내 미션 정보 전달이 추가되어 정확한 미션 화면으로 이동합니다.
    • 버튼 컴포넌트에 최대 너비 사용 여부를 선택할 수 있는 옵션이 추가되었습니다.
  • 문서 및 리소스

    • 미션 관련 텍스트 및 안내 문구가 다수 추가되었습니다.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 23, 2025

"""

Walkthrough

알람 미션 종류 및 횟수 설정 기능이 추가되었습니다. 알람 추가/수정 화면에서 미션 종류와 횟수를 선택할 수 있는 바텀시트 UI가 도입되었으며, 관련 상태, 액션, 뷰모델, 문자열 리소스 등이 확장되었습니다. 미션 화면으로의 딥링크와 인텐트에도 미션 타입과 카운트가 전달되도록 변경되었습니다. 미션 진행 로직도 카운트 기반으로 통합되었습니다.

Changes

파일/경로 요약 변경 내용 요약
core/alarm/.../AlarmDismissPendingIntent.kt, core/alarm/.../AlarmService.kt 미션 타입 및 카운트 파라미터를 인텐트 생성 함수에 추가, 알람 딥링크 인텐트에 미션 정보 포함
core/designsystem/.../drawable/ic_delete.xml, ic_mission_shake.xml, ic_mission_tap.xml 미션 및 삭제 관련 신규 벡터 드로어블 리소스 추가
feature/home/.../AlarmAddEditContract.kt, AlarmAddEditScreen.kt, AlarmAddEditViewModel.kt 알람 미션 상태에 카운트 필드 추가, 미션 바텀시트 액션 및 상태 처리, 미션 정보 저장 로직 추가
feature/home/.../component/AlarmListItem.kt 알람 시간 계산 함수에서 isAm 파라미터 제거 및 24시간제 적용
feature/home/.../component/SelectorItems.kt 선택형 라디오 버튼 UI 컴포넌트 신규 추가
feature/home/.../component/bottomsheet/AlarmMissionBottomSheet.kt 미션 설정/선택/상세 바텀시트 UI 신규 추가
feature/home/.../component/bottomsheet/AlarmSnoozeBottomSheet.kt SelectorItems 내장 구현 제거, 외부 컴포넌트 사용으로 변경
feature/home/.../res/values/strings.xml 미션 관련 문자열 리소스 다수 추가
feature/mission/.../MissionContract.kt, MissionScreen.kt, MissionViewModel.kt, MissionNavGraph.kt, component/FlipCard.kt 미션 카운트/진행상황을 단일 currentCount로 통합, 미션 타입/카운트 딥링크 파라미터 추가, 관련 UI 및 상태 로직 일원화
core/ui/.../OrbitButton.kt OrbitButton에 선택적 fillMaxWidth 파라미터 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AlarmAddEditScreen
    participant AlarmMissionBottomSheet
    participant AlarmAddEditViewModel
    participant AlarmService
    participant MissionScreen

    User->>AlarmAddEditScreen: 알람 추가/수정 화면 진입
    User->>AlarmAddEditScreen: 미션 설정 클릭
    AlarmAddEditScreen->>AlarmMissionBottomSheet: 미션 바텀시트 표시
    User->>AlarmMissionBottomSheet: 미션 타입/횟수 선택 후 저장
    AlarmMissionBottomSheet->>AlarmAddEditScreen: onSaveMission 콜백
    AlarmAddEditScreen->>AlarmAddEditViewModel: SaveMission 액션 전달
    AlarmAddEditViewModel->>AlarmAddEditViewModel: 미션 상태 업데이트

    User->>AlarmService: 알람 울림
    AlarmService->>AlarmDismissPendingIntent: 미션 타입/카운트 포함 인텐트 생성
    AlarmService->>MissionScreen: 딥링크로 미션 화면 호출 (notificationId, missionType, missionCount)
    MissionScreen->>MissionScreen: missionCount, currentCount로 미션 진행 UI 갱신
Loading

Estimated code review effort

4 (~90분)

Possibly related PRs

Suggested reviewers

  • MoonsuKang
    """

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 991743e and 6215002.

📒 Files selected for processing (1)
  • feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt
⏰ 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: build
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@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

🔭 Outside diff range comments (1)
core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt (1)

115-115: shouldNavigateToMission() 및 관련 파라미터 제거 제안
현재 createNotification(alarm, shouldNavigateToMission()) 호출을 통해 반환된 불리언 값이 함수 내부 로직에서 전혀 사용되지 않습니다. 따라서 불필요한 함수 호출과 파라미터를 제거하여 코드를 정리해주세요.

• core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt

  • when 블록에서
    createNotification(alarm, shouldNavigateToMission())
    createNotification(alarm)
  • shouldNavigateToMission() 함수 선언 삭제
  • createNotification 시그니처에서 shouldNavigateToMission: Boolean 파라미터 제거
  • 필요 시 alarmDismissPendingIntent 로직에 맞춰 조건 분기(주석 처리된 부분) 재도입 또는 파라미터 완전 제거
🧹 Nitpick comments (4)
feature/home/src/main/java/com/yapp/home/alarm/component/SelectorItems.kt (1)

20-67: 재사용 가능한 컴포넌트가 잘 설계되었습니다.

SelectorItems 컴포넌트가 명확한 인터페이스와 적절한 시각적 피드백을 제공합니다. AlarmSnoozeBottomSheet에서 중복 코드를 제거하고 재사용성을 높이는 좋은 리팩토링입니다.

입력 검증을 추가하여 컴포넌트를 더욱 견고하게 만들 수 있습니다:

@Composable
internal fun SelectorItems(
    items: List<String>,
    selectedIndex: Int,
    enabled: Boolean,
    onItemSelected: (Int) -> Unit,
) {
+    require(items.isNotEmpty()) { "Items list cannot be empty" }
+    require(selectedIndex in items.indices) { "Selected index must be within items range" }
+    
    Box {
        // ... rest of the implementation
    }
}
core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt (1)

144-156: 주석 처리된 코드는 제거하는 것을 고려해보세요.

이전 조건부 로직이 주석 처리되어 있습니다. 새로운 구현이 확정되면 주석 코드를 제거하여 코드 가독성을 높이는 것을 권장합니다.

feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (1)

54-54: 미션 횟수 옵션이 하드코딩되어 있습니다.

countOptions이 컴파일 타임에 고정되어 있어 향후 확장성이 제한될 수 있습니다.

더 유연한 구조를 위해 다음과 같이 개선을 고려해보세요:

-private val countOptions = listOf(5, 10, 15, 20, 30)
+@Composable
+private fun getCountOptions(): List<Int> {
+    // 향후 사용자 설정이나 원격 구성으로 확장 가능
+    return listOf(5, 10, 15, 20, 30)
+}
feature/home/src/main/res/values/strings.xml (1)

54-55: 난이도 레벨 문자열의 의미를 검토해 주세요.

"쉬움"과 "어려움"이 미션 횟수와 어떻게 연관되는지 사용자에게 명확하지 않을 수 있습니다.

더 직관적인 표현을 고려해보세요:

-    <string name="mission_detail_content_count_level_easy">쉬움</string>
-    <string name="mission_detail_content_count_level_hard">어려움</string>
+    <string name="mission_detail_content_count_level_easy">적게</string>
+    <string name="mission_detail_content_count_level_hard">많이</string>
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3863bfe and 512082d.

📒 Files selected for processing (18)
  • core/alarm/src/main/java/com/yapp/alarm/pendingIntent/interaction/AlarmDismissPendingIntent.kt (2 hunks)
  • core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_delete.xml (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_mission_shake.xml (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_mission_tap.xml (1 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditContract.kt (4 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt (4 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditViewModel.kt (5 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/component/AlarmListItem.kt (1 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/component/SelectorItems.kt (1 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (1 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmSnoozeBottomSheet.kt (1 hunks)
  • feature/home/src/main/res/values/strings.xml (1 hunks)
  • feature/mission/src/main/java/com/yapp/mission/MissionContract.kt (1 hunks)
  • feature/mission/src/main/java/com/yapp/mission/MissionNavGraph.kt (1 hunks)
  • feature/mission/src/main/java/com/yapp/mission/MissionScreen.kt (5 hunks)
  • feature/mission/src/main/java/com/yapp/mission/MissionViewModel.kt (5 hunks)
  • feature/mission/src/main/java/com/yapp/mission/component/FlipCard.kt (1 hunks)
🔇 Additional comments (43)
core/designsystem/src/main/res/drawable/ic_mission_shake.xml (1)

1-18: 아이콘 리소스가 잘 구성되어 있습니다.

벡터 드로어블이 Android 표준을 준수하며, 29x29dp 크기와 viewport가 일치합니다. SHAKE 미션을 위한 시각적 디자인이 적절합니다.

core/designsystem/src/main/res/drawable/ic_mission_tap.xml (1)

1-27: 미션 아이콘 크기 차이 확인 필요

스크립트 실행 결과, ic_mission_shake.xml은 29×29dp, ic_mission_tap.xml은 27×27dp로 정의되어 있어 크기가 상이함을 확인했습니다.

• core/designsystem/src/main/res/drawable/ic_mission_shake.xml: android:width="29dp", android:height="29dp"
• core/designsystem/src/main/res/drawable/ic_mission_tap.xml: android:width="27dp", android:height="27dp"

미션 아이콘들 간 크기 차이가 의도된 것인지 확인 부탁드립니다. 의도된 차이가 아니라면, 모든 미션 아이콘을 동일한 크기로 조정해 주세요.

feature/home/src/main/java/com/yapp/home/alarm/component/AlarmListItem.kt (2)

292-302: 함수 호출부도 올바르게 업데이트되었습니다.

toRepeatDaysString 함수에서 getNextAlarmDateWithTime 호출 시 isAm 파라미터가 제거되어 새로운 함수 시그니처와 일치합니다.


317-331: 시간 처리 로직 단순화 확인 및 호출 지점 업데이트 완료

  • getNextAlarmDateWithTime(hour: Int, minute: Int) 호출 지점이 모두 새로운 시그니처로 변경되었습니다.
  • 기존 isAm 파라미터가 제거된 것이 일관되게 적용되었습니다.

다음 사항만 추가로 검증해주세요:

  • 알람 데이터 모델이 24시간 형식으로 저장되도록 데이터 일관성(기존 데이터 마이그레이션, DB 스키마 등)을 확인해 주세요.
feature/home/src/main/java/com/yapp/home/alarm/component/SelectorItems.kt (1)

69-74: 정렬 로직이 명확합니다.

getAlignment 헬퍼 함수가 첫 번째, 마지막, 중간 아이템들의 정렬을 명확하게 처리합니다.

feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmSnoozeBottomSheet.kt (1)

28-28: 컴포넌트 리팩토링이 성공적으로 완료되었습니다.

로컬 SelectorItems 구현을 제거하고 외부 컴포넌트를 사용하도록 변경하여 코드 중복을 제거하고 재사용성을 높였습니다. 기능적 변경 없이 코드 품질이 향상되었습니다.

feature/mission/src/main/java/com/yapp/mission/component/FlipCard.kt (1)

52-53: 통합된 카운터 로직으로 올바르게 변경되었습니다.

shakeCount에서 currentCount로 변경된 것이 미션 진행 상태 통합 리팩토링과 일치하며, 애니메이션 로직이 올바르게 작동합니다.

core/designsystem/src/main/res/drawable/ic_delete.xml (1)

1-16: 잘 구현된 벡터 드로어블입니다.

Android 벡터 드로어블 표준을 준수하며, 적절한 크기와 색상으로 정의되었습니다. fillType="evenOdd"를 사용한 것도 겹치는 도형이 있는 복잡한 아이콘에 적합합니다.

feature/mission/src/main/java/com/yapp/mission/MissionContract.kt (1)

10-11: 미션 진행 상태 통합이 잘 구현되었습니다.

별도의 shakeCount, clickCount를 단일 currentCount로 통합하고 missionCount를 추가하여 동적 미션 설정이 가능해졌습니다. 기본값도 적절하게 설정되었습니다.

feature/mission/src/main/java/com/yapp/mission/MissionNavGraph.kt (1)

18-18: 딥링크 파라미터 추가가 올바르게 구현되었습니다.

missionTypemissionCount 파라미터가 딥링크 URI 패턴에 추가되어 알람에서 미션 화면으로 미션 설정 정보를 전달할 수 있게 되었습니다.

core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt (1)

137-142: 알람 해제 인텐트 생성 로직이 단순화되었습니다.

항상 미션 화면으로 이동하는 인텐트를 생성하도록 변경되었으며, missionTypemissionCount 파라미터가 올바르게 전달됩니다.

feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditContract.kt (4)

49-49: 미션 카운트 기본값이 적절하게 설정되었습니다.

미션 카운트의 기본값 10은 사용자 경험 측면에서 합리적인 선택입니다.


87-87: 미션 저장 액션이 올바르게 정의되었습니다.

SaveMission 액션의 매개변수 타입과 네이밍이 기존 패턴을 잘 따르고 있습니다.


98-98: 바텀시트 타입이 일관되게 추가되었습니다.

MissionSetting이 기존 바텀시트 타입들과 동일한 패턴으로 구현되었습니다.


131-132: 도메인 모델 매핑이 올바르게 구현되었습니다.

미션 상태가 알람 도메인 모델로 정확하게 변환되고 있습니다.

core/alarm/src/main/java/com/yapp/alarm/pendingIntent/interaction/AlarmDismissPendingIntent.kt (2)

38-46: 함수 시그니처 변경이 올바르게 구현되었습니다.

미션 타입과 카운트 매개변수가 적절히 추가되고 올바르게 전달되고 있습니다. 이는 breaking change이지만 미션 기능 통합을 위해 필요한 변경입니다.


58-66: 딥링크 URI 구성이 올바르게 구현되었습니다.

미션 관련 매개변수들이 적절한 쿼리 파라미터 형식으로 URI에 포함되어 있습니다.

feature/mission/src/main/java/com/yapp/mission/MissionScreen.kt (4)

153-153: 통합된 카운터 사용으로 코드 일관성이 향상되었습니다.

currentCount를 사용한 초기 상태 체크가 미션 타입별로 일관되게 적용되어 코드의 가독성과 유지보수성이 개선되었습니다.

Also applies to: 270-270


216-217: 진행률 바 구현이 명확하고 정확합니다.

currentCount와 missionCount를 사용한 진행률 계산이 직관적이며 동적 미션 카운트 설정을 잘 지원합니다.


232-233: 미션 라벨 구현이 일관되고 동적으로 작동합니다.

목표 카운트와 현재 카운트가 명확하게 표시되며, 두 미션 타입 모두 동일한 패턴을 사용하여 일관성이 확보되었습니다.


407-409: 프리뷰 상태가 적절하게 구성되었습니다.

개발 및 테스트를 위한 현실적인 초기 미션 상태가 제공되어 UI 컴포넌트 검증에 도움이 됩니다.

feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditViewModel.kt (5)

13-13: 필요한 임포트가 적절히 추가되었습니다.

미션 기능 구현을 위해 MissionType 도메인 모델 임포트가 올바르게 추가되었습니다.


111-111: 미션 상태 초기화가 기존 패턴과 일관되게 통합되었습니다.

기존 알람 로딩 시 미션 상태 설정이 다른 상태 초기화 메서드들과 동일한 패턴으로 구현되었습니다.


136-144: 미션 상태 설정 메서드가 올바르게 구현되었습니다.

메서드가 기존 알람으로부터 미션 데이터를 적절히 추출하고, 불변성 원칙을 따라 새 상태 인스턴스를 반환합니다.


183-183: SaveMission 액션 처리가 기존 패턴을 잘 따릅니다.

액션 매개변수가 올바르게 추출되어 구현 메서드로 전달되고 있습니다.


440-448: 미션 저장 메서드가 MVI 패턴을 올바르게 따릅니다.

불변성을 유지하면서 상태를 업데이트하고, 기존 상태 업데이트 메서드들과 일관된 구현 패턴을 보여줍니다.

feature/home/src/main/java/com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt (4)

61-61: 미션 바텀시트 컴포넌트 임포트가 적절히 추가되었습니다.

새로운 미션 설정 UI를 위해 필요한 임포트가 올바르게 추가되었습니다.


171-173: 미션 상태 관리와 바텀시트 설정이 일관되게 구현되었습니다.

상태 추출로 코드 가독성이 향상되었고, 바텀시트 구성이 다른 시트들과 동일한 패턴을 따릅니다.


224-246: 미션 바텀시트 통합이 올바르게 구현되었습니다.

상태 관리와 이벤트 처리가 기존 패턴을 잘 따르고 있습니다. 미션 프리뷰 기능이 아직 구현되지 않은 것은 PR 목표에서 언급된 미완성 작업으로 이해됩니다.


448-476: 미션 설명 표시 로직이 포괄적이고 사용자 친화적으로 구현되었습니다.

미션 타입과 카운트가 명확하게 표시되고, 국제화를 위한 문자열 리소스 사용과 적절한 클릭 상호작용이 구현되었습니다.

feature/mission/src/main/java/com/yapp/mission/MissionViewModel.kt (5)

34-34: 생성자 매개변수 private 접근 제한자 적용이 적절합니다.

savedStateHandle을 private으로 선언하여 캡슐화를 개선했습니다.


43-43: 메서드명 변경이 기능을 명확히 반영합니다.

loadRemoteMissionType()에서 loadMissionInfo()로 변경하여 미션 타입과 횟수를 모두 로드하는 기능을 더 명확히 표현합니다.


83-87: 미션 진행 상태 업데이트 로직이 개선되었습니다.

currentCount를 사용하여 통합된 카운팅 로직으로 변경되었고, missionCount를 동적으로 사용하여 더 유연한 구조가 되었습니다.


103-107: TAP 미션의 카운팅 로직도 일관성 있게 개선되었습니다.

SHAKE와 동일한 패턴으로 currentCountmissionCount를 사용하여 일관된 로직을 구현했습니다.


56-70: SavedStateHandle 기본값 처리 및 Navigation 파라미터 정의 검증 요청

loadMissionInfo()에서 toIntOrNull() ?: default가 의도대로 동작하는지, 그리고 네비게이션에서 missionType·missionCount 파라미터가 올바르게 선언되어 있는지 직접 확인해주세요.

확인해야 할 위치:

  • feature/mission/src/main/java/com/yapp/mission/MissionNavGraph.kt
    composable<MissionRoute> 호출부에
    – arguments = listOf(navArgument("missionType"){…}, navArgument("missionCount"){…}) 정의 여부
    uriPattern 외에 navArgument 기본값 설정 유무
  • MissionRoute 경로 생성 로직
    route 또는 createRoute() 함수에서 쿼리 파라미터 포맷과 기본값 처리 확인

위 항목들을 검토한 후, 잘못된 값이 들어왔을 때 MissionViewModel의 기본값 처리가 정확히 적용되는지 확인 부탁드립니다.

feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (5)

48-52: 바텀시트 단계 관리를 위한 enum 정의가 명확합니다.

미션 설정, 선택, 상세 단계를 명확히 구분하여 UI 상태 관리를 체계적으로 구현했습니다.


73-76: 내부 상태 관리 패턴이 적절합니다.

remember를 사용하여 선택된 미션 타입과 횟수를 내부적으로 관리하는 방식이 바텀시트의 일시적 상태 특성에 적합합니다.


165-166: 고정 높이 설정을 검토해 주세요.

height(600.dp)로 고정 높이를 설정했는데, 다양한 화면 크기에서 적절한지 확인이 필요합니다.

다양한 화면 크기에서 바텀시트 높이가 적절한지 테스트해 주세요. 특히 작은 화면에서 콘텐츠가 잘리지 않는지 확인이 필요합니다.


483-483: 인덱스 안전성 처리가 잘 되어 있습니다.

coerceAtLeast(0)를 사용하여 인덱스 오류를 방지하는 방어적 프로그래밍이 적용되었습니다.


553-558: SelectorItems 재사용성이 좋습니다.

공통 컴포넌트인 SelectorItems를 재사용하여 일관된 UI 패턴을 유지하고 코드 중복을 방지했습니다.

feature/home/src/main/res/values/strings.xml (3)

36-36: 포맷 문자열이 올바르게 정의되었습니다.

미션 타입과 횟수를 함께 표시하는 포맷 문자열이 적절히 구현되었습니다.


41-42: 문자열 리소스 구조화가 잘 되어 있습니다.

주석을 통해 관련 문자열들을 그룹화하여 가독성과 유지보수성을 높였습니다.


51-51: 일관된 포맷 문자열 네이밍을 적용했습니다.

mission_count_chip_format과 같이 용도가 명확한 네이밍 규칙을 사용했습니다.

Comment on lines +56 to +60
private fun MissionType.displayData(): Pair<Int, Int> = when (this) {
MissionType.SHAKE -> Pair(R.drawable.ic_mission_shake, feature.home.R.string.alarm_add_edit_selected_mission_shake)
MissionType.TAP -> Pair(R.drawable.ic_mission_tap, feature.home.R.string.alarm_add_edit_selected_mission_tap)
else -> throw IllegalStateException("Invalid mission type")
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

MissionType 확장 함수에서 예외 처리를 개선해 주세요.

else 분기에서 IllegalStateException을 발생시키지만, 더 구체적인 예외 메시지와 함께 방어적 프로그래밍을 적용하는 것이 좋겠습니다.

-    else -> throw IllegalStateException("Invalid mission type")
+    else -> throw IllegalArgumentException("Unsupported mission type: $this")
🤖 Prompt for AI Agents
In
feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt
around lines 56 to 60, improve the exception handling in the
MissionType.displayData() extension function by replacing the generic
IllegalStateException with a more specific exception message that includes the
invalid mission type value. This enhances defensive programming by providing
clearer context when an unexpected MissionType is encountered.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jul 23, 2025

Codecov Report

❌ Patch coverage is 0% with 537 lines in your changes missing coverage. Please review.
✅ Project coverage is 4.23%. Comparing base (d38d230) to head (6215002).
⚠️ Report is 17 commits behind head on develop.

Files with missing lines Patch % Lines
...m/component/bottomsheet/AlarmMissionBottomSheet.kt 0.00% 429 Missing ⚠️
...ava/com/yapp/home/alarm/component/SelectorItems.kt 0.00% 41 Missing ⚠️
.../com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt 0.00% 40 Missing ⚠️
...m/yapp/home/alarm/addedit/AlarmAddEditViewModel.kt 0.00% 12 Missing ⚠️
...ingIntent/interaction/AlarmDismissPendingIntent.kt 0.00% 7 Missing ⚠️
...om/yapp/home/alarm/addedit/AlarmAddEditContract.kt 0.00% 5 Missing ⚠️
.../main/java/com/yapp/alarm/services/AlarmService.kt 0.00% 2 Missing ⚠️
...ava/com/yapp/home/alarm/component/AlarmListItem.kt 0.00% 1 Missing ⚠️

❌ Your project status has failed because the head coverage (4.23%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##             develop    #234      +/-   ##
============================================
- Coverage       4.75%   4.23%   -0.52%     
  Complexity        53      53              
============================================
  Files             48      50       +2     
  Lines           3976    4462     +486     
  Branches         622     659      +37     
============================================
  Hits             189     189              
- Misses          3777    4263     +486     
  Partials          10      10              
Files with missing lines Coverage Δ
...rm/component/bottomsheet/AlarmSnoozeBottomSheet.kt 0.00% <ø> (ø)
...ava/com/yapp/home/alarm/component/AlarmListItem.kt 0.00% <0.00%> (ø)
.../main/java/com/yapp/alarm/services/AlarmService.kt 0.00% <0.00%> (ø)
...om/yapp/home/alarm/addedit/AlarmAddEditContract.kt 0.00% <0.00%> (ø)
...ingIntent/interaction/AlarmDismissPendingIntent.kt 0.00% <0.00%> (ø)
...m/yapp/home/alarm/addedit/AlarmAddEditViewModel.kt 0.00% <0.00%> (ø)
.../com/yapp/home/alarm/addedit/AlarmAddEditScreen.kt 0.00% <0.00%> (ø)
...ava/com/yapp/home/alarm/component/SelectorItems.kt 0.00% <0.00%> (ø)
...m/component/bottomsheet/AlarmMissionBottomSheet.kt 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

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

♻️ Duplicate comments (1)
feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (1)

56-60: 예외 처리 개선이 필요합니다.

이전 리뷰에서 언급된 대로, else 분기에서 더 구체적인 예외 처리가 필요합니다.

-    else -> throw IllegalStateException("Invalid mission type")
+    else -> throw IllegalArgumentException("Unsupported mission type: $this")
🧹 Nitpick comments (1)
feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (1)

165-165: 하드코딩된 높이 값을 상수로 추출해 주세요.

height(600.dp) 값이 여러 곳에서 반복 사용되고 있습니다. 일관성과 유지보수성을 위해 상수로 추출하는 것이 좋겠습니다.

파일 상단에 상수를 추가하세요:

 private val countOptions = listOf(5, 10, 15, 20, 30)
+private val BOTTOM_SHEET_HEIGHT = 600.dp

그리고 사용하는 곳에서:

-            .height(600.dp)
+            .height(BOTTOM_SHEET_HEIGHT)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 512082d and 991743e.

📒 Files selected for processing (4)
  • core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt (1 hunks)
  • core/ui/src/main/java/com/yapp/ui/component/button/OrbitButton.kt (2 hunks)
  • feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (1 hunks)
  • feature/mission/src/main/java/com/yapp/mission/component/FlipCard.kt (1 hunks)
🧠 Learnings (1)
core/ui/src/main/java/com/yapp/ui/component/button/OrbitButton.kt (1)

Learnt from: DongChyeon
PR: #233
File: domain/src/main/java/com/yapp/domain/usecase/AlarmUseCase.kt:38-61
Timestamp: 2025-07-16T14:32:09.264Z
Learning: In the Orbit-Android project, the team prefers to focus unit testing on core business logic rather than UseCase wrapper methods to avoid unnecessary dependency mocking costs. They consider it sufficient to test the main formatting logic (like formatTimeDifference) rather than testing thin wrapper methods in UseCases.

🚧 Files skipped from review as they are similar to previous changes (2)
  • core/alarm/src/main/java/com/yapp/alarm/services/AlarmService.kt
  • feature/mission/src/main/java/com/yapp/mission/component/FlipCard.kt
🧰 Additional context used
🧠 Learnings (1)
core/ui/src/main/java/com/yapp/ui/component/button/OrbitButton.kt (1)

Learnt from: DongChyeon
PR: #233
File: domain/src/main/java/com/yapp/domain/usecase/AlarmUseCase.kt:38-61
Timestamp: 2025-07-16T14:32:09.264Z
Learning: In the Orbit-Android project, the team prefers to focus unit testing on core business logic rather than UseCase wrapper methods to avoid unnecessary dependency mocking costs. They consider it sufficient to test the main formatting logic (like formatTimeDifference) rather than testing thin wrapper methods in UseCases.

🔇 Additional comments (4)
core/ui/src/main/java/com/yapp/ui/component/button/OrbitButton.kt (1)

36-36: 잘 구현된 기능 확장입니다!

useFillMaxWidth 매개변수 추가가 깔끔하게 구현되었습니다. 기본값이 true로 설정되어 기존 동작을 유지하면서, 새로운 바텀시트 컴포넌트에서 필요한 가변 너비 동작을 지원합니다.

Also applies to: 81-83

feature/home/src/main/java/com/yapp/home/alarm/component/bottomsheet/AlarmMissionBottomSheet.kt (3)

481-481: early return 사용이 적절합니다.

when 표현식에서 else -> return을 사용하여 예상치 못한 MissionType에 대해 조기 반환하는 것은 좋은 방어적 프로그래밍입니다.


553-558: SelectorItems 사용법이 올바릅니다.

countOptions를 문자열 리스트로 변환하고 선택된 인덱스를 올바르게 처리하는 로직이 잘 구현되어 있습니다. coerceAtLeast(0)을 사용한 안전 처리도 적절합니다.


571-571: OrbitButton의 새로운 기능을 잘 활용했습니다.

useFillMaxWidth = false를 사용하여 미리보기 버튼이 컨텐츠에 맞는 크기로 조정되도록 한 것이 UI 디자인에 적합합니다.

Copy link
Copy Markdown
Member

@MoonsuKang MoonsuKang left a comment

Choose a reason for hiding this comment

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

굿굿 고생하셧습니다. 이벤트 중에 {} 로 된 곳은 다음 PR때 올라오는 거죠잉?

Comment on lines +56 to +60
onDismissRequest = {
scope.launch {
sheetState.hide()
}.invokeOnCompletion { onDismiss() }
},
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.

P5
어 혹시 onDismiss() 이거랑 다른게 있을까요? 궁금해서요!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

요것도.... 계속 수정하다보니 Outdated된 변경 사항이네요

OrbitBottomSheet(
    isSheetOpen = isSheetOpen,
    sheetState = sheetState,
    onDismissRequest = {
        currentStep = AlarmMissionSelectBottomSheetType.MISSION_SETTING
        onDismiss()
    },
) { 
    // ...
}

현재는 onDismiss 호출합니다.

Comment on lines +27 to +28
Box {
Column {
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.

P4
수직 배열이면 Column도 괜찮지 않을까요? Box가 필요한 이유가 있는지 궁금함다!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

image

해당 컴포넌트를 구현하기 위해 선을 긋고 위에 선택할 수 있는 동그라미 버튼을 올려놓은 형태이므로 Box를 통해 오버레이했습니다.

Text(
modifier = Modifier.align(Alignment.Start),
text = "미션 선택",
text = "미션",
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.

P5
피그마 보니까 이해가 잘 안되는데 미션 or 미션 선택?? 인가유?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

미션이 맞습니다!

Comment on lines +351 to +356
Text(
text = "어려움",
style = OrbitTheme.typography.label2SemiBold,
color = OrbitTheme.colors.gray_300,
)
}
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.

1

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 알람 설정 시 미션 종류 선택 기능 추가하기

2 participants