Skip to content

[FEAT/#67] 시술 뷰 UI 구현#84

Merged
usuuhyn merged 45 commits intodevelopfrom
feat/#67-procedure-view
Jan 19, 2026
Merged

[FEAT/#67] 시술 뷰 UI 구현#84
usuuhyn merged 45 commits intodevelopfrom
feat/#67-procedure-view

Conversation

@usuuhyn
Copy link
Copy Markdown
Contributor

@usuuhyn usuuhyn commented Jan 18, 2026

Related issue 🛠

Work Description ✏️

  • 시술 뷰 UI를 구현했습니다.

Screenshot 📸

Treat NoTreat
video video

Uncompleted Tasks 😅

N/A

To Reviewers 📢

드디어 완성햇어요

Summary by CodeRabbit

  • 새 기능

    • 캘린더에서 절차(Procedure) 다단계 흐름으로 이동하는 내비게이션 및 절차 화면/컴포저블 추가
    • 절차 흐름용 UI 상태 모델과 이를 관리하는 뷰모델 도입
    • 캘린더의 추가 버튼으로 절차 이동을 트리거하는 사이드이펙트 및 콜백 추가
  • UI 개선

    • 단계 진행 표시 애니메이션 개선(뒤로/앞으로 전환 처리 보강)
    • 카드 선택 단일→다중 선택 확장 및 검색/필터링의 하단 패딩 제어 추가
    • 일부 컴포저블에 modifier 전달 지원 및 복구 일정에 오류 메시지 표시
    • 다운타임 관련 검증 타입 및 하단시트 동작 보완
  • 기타

    • 상태·내비게이션 바에 다크·투명 엣지 투 엣지 스타일 적용

✏️ Tip: You can customize this high-level summary in your review settings.

- 초기단계일 때도 애니메이션 동작되도록 수정
- 뒤로 가는 애니메이션 추가
- ProcedureUiState
lazyColumnBottomPadding 계산 로직 추가
- FilteringContent, FilteringWithSearchContent에 bottomPadding 파라미터 전달
- 바텀시트 표시 시 컨텐츠가 가려지지 않도록 동적 패딩 적용
- 화면 높이 기반으로 바텀시트 최대 높이(30%) 계산
@usuuhyn usuuhyn self-assigned this Jan 18, 2026
@usuuhyn usuuhyn requested a review from a team as a code owner January 18, 2026 14:18
@usuuhyn usuuhyn added FEAT✨ 새로운 기능 구현 수현🍒 수현 담당 labels Jan 18, 2026
@usuuhyn usuuhyn linked an issue Jan 18, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 18, 2026

Caution

Review failed

An error occurred during the review process. Please try again later.

Walkthrough

달력 화면에 시술(Procedure) 플로우를 새로 추가하고, 라우트·스크린·뷰모델·UiState·도메인 모델·컴포넌트들을 도입·재배치했으며, 달력 쪽에는 사이드이펙트 기반 네비게이션(onNavigateToProcedure)과 NavController 확장(navigateToProcedure)을 연결했습니다.

Changes

Cohort / File(s) 변경 요약
네비게이션 / Calendar 연동
app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt, app/src/main/java/com/cherrish/android/presentation/calendar/navigation/CalendarNavigator.kt, app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt, app/src/main/java/com/cherrish/android/presentation/main/MainAppState.kt
CalendarRoute에 onNavigateToProcedure 콜백 추가 및 collectLatestSideEffect 수집, NavController.navigateToProcedure() 추가, calendarNavGraph 시그니처 확장(navigateUp, navigateToProcedure) 및 MainScreen/MainAppState에서 위임/호출 연결.
Procedure 라우트 · 스크린 · 컴포저블
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt
신규 ProcedureRouteProcedureScreen 추가 — ProcedureViewModel.uiState 관찰, 단계별 렌더링, 하단 시트/피커/네비게이션 콜백과 완료/뒤로 동작 처리.
상태 모델 / 뷰모델
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureUiState.kt, app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureViewModel.kt
ProcedureUiState(검증/계산 프로퍼티, 샘플 데이터) 및 ProcedureViewModel(다수 공개 핸들러: 선택, 날짜/다운타임, Next/Back/Complete 등) 신규 추가.
도메인 모델 / 유틸
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/model/*, app/src/main/java/com/cherrish/android/presentation/calendar/procedure/util/DowntimeDayLogic.kt
ProcedureFlow/ProcedureStep/ProcedureWithDowntime/DowntimeValidationType 도입 및 DowntimeDayLogic 패키지 이동/임포트 조정.
콘텐츠 컴포저블 시그니처 변경
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/content/*
Existence/Category에 modifier 추가, RecoverySchedule에 errorMessage 추가, Downtime/Filtering/FilteringWithSearch 등 단일선택→다중선택 전환 및 bottomPadding 파라미터 도입.
컴포넌트 애니메이션·패키지 변경
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/StepProgressBar.kt, app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt
StepProgressBar에 Animatable 기반 애니메이션·이전 인덱스·방향 추적 로직 추가; DowntimeBottomSheet 패키지 경로 변경 및 DowntimeValidationType 처리 추가.
앱 외관 설정 변경
app/src/main/java/com/cherrish/android/presentation/main/MainActivity.kt
enableEdgeToEdge() 호출을 status/navigation bar에 dark transparent 스타일 적용 버전으로 교체.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Calendar as CalendarRoute
    participant VM_Cal as CalendarViewModel
    participant Nav as NavController
    participant Procedure as ProcedureRoute
    participant VM_Proc as ProcedureViewModel
    participant Sheet as DowntimeBottomSheet

    User->>Calendar: 시술 추가 버튼 클릭
    Calendar->>VM_Cal: onAddButtonClick()
    VM_Cal-->>Calendar: emit CalendarSideEffect.NavigateToProcedure
    Calendar->>Nav: navigateToProcedure()
    Nav->>Procedure: compose ProcedureRoute
    Procedure->>VM_Proc: collect uiState
    VM_Proc-->>Procedure: uiState emit
    User->>Procedure: 단계별 입력/선택
    Procedure->>VM_Proc: onExistenceClick/onProcedureCardClick/onYearChange...
    VM_Proc-->>Procedure: 업데이트된 uiState
    Procedure->>Sheet: show DowntimeBottomSheet (필요 시)
    User->>Sheet: downtime 선택 및 확인
    Sheet->>VM_Proc: onDowntimeConfirm()
    VM_Proc-->>Procedure: 업데이트된 uiState
    User->>Procedure: 완료 -> onComplete -> navigateUp
    Procedure->>Nav: popBackStack()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • sohee6989
  • nhyeonii
  • hyeminililo
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
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.
Out of Scope Changes check ❓ Inconclusive MainActivity의 엣지투엣지 스타일 변경이 시술 뷰 UI 구현의 범위 밖이지만, 대부분의 변경사항은 #67 이슈 목표와 직접 관련됩니다. MainActivity의 SystemBarStyle 변경이 절대적으로 필요한지 확인하거나, 이를 별도의 PR으로 분리하는 것을 고려하세요.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 시술 뷰 UI 구현이라는 주요 변경사항을 명확하게 요약하고 있으며, 변경사항과 완전히 일치합니다.
Description check ✅ Passed PR 설명이 템플릿 구조를 준수하며 관련 이슈, 작업 설명, 스크린샷을 포함하고 있으나 세부 내용이 간략합니다.
Linked Issues check ✅ Passed PR은 #67 이슈의 시술 플로우 뷰 조립 목표를 완전히 충족하며, 필요한 모든 UI 컴포넌트와 네비게이션 로직을 구현했습니다.

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


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.

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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt`:
- Around line 216-223: FilteringWithSearchContent의 onSearchAction이 TODO로 남아 있어
검색 버튼(액션)이 동작하지 않습니다; ProcedureScreen에서 해당 콜백을 ViewModel의 검색 핸들러로 연결하고
ViewModel에 검색 처리 로직을 구현하세요. 구체적으로는 ProcedureScreen의 FilteringWithSearchContent
호출에서 onSearchAction = viewModel::onSearchAction(또는 viewModel.searchProcedures)로
바꾸고, ViewModel에 onSearchAction(query: String) 또는 searchProcedures() 메서드를 추가해
uiState.query를 업데이트하고 procedureItems를 필터링 또는 검색 API 호출로 갱신하도록 상태 업데이트 로직을 구현하세요;
필요한 경우 선택된 카드(uiState.selectedProcedureCardIds)나 페이징/빈 상태 처리도 함께 업데이트하도록 하세요.
♻️ Duplicate comments (2)
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt (2)

54-57: Loading/Failure에서 사용자 피드백이 비어 있습니다.
Line 55-56에서 Unit만 반환되어 로딩/실패 상태가 빈 화면으로 보입니다.


181-186: 외부 modifier 전달로 하위 레이아웃이 예기치 않게 영향받을 수 있습니다.
Line 185에서 외부 modifier를 그대로 전달해 다른 콘텐츠와 일관성이 깨집니다. 내부용 Modifier로 고정하는 편이 안전합니다.

🛠️ 수정 제안
-                                modifier = modifier.padding(horizontal = 26.dp)
+                                modifier = Modifier.padding(horizontal = 26.dp)

Comment on lines +216 to +223
FilteringWithSearchContent(
cardItems = uiState.procedureItems,
selectedCardIds = uiState.selectedProcedureCardIds,
onCardClick = onProcedureCardClick,
onSearchAction = { /* TODO */ },
query = query,
onQueryChange = { query = it },
bottomPadding = uiState.lazyColumnBottomPadding,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "ProcedureScreen.kt" | head -20

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 165


🏁 Script executed:

find . -type f -name "ProcedureViewModel.kt" | head -20

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 168


🏁 Script executed:

find . -type f -name "ProcedureRoute.kt" | head -20

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

cat -n ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt | sed -n '210,230p'

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1299


🏁 Script executed:

grep -n "fun ProcedureRoute\|fun ProcedureScreen" ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt | head -20

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 120


🏁 Script executed:

grep -n "onSearchAction" ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 142


🏁 Script executed:

grep -n "onSearchAction\|fun on" ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureViewModel.kt | head -30

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 676


🏁 Script executed:

cat -n ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt | sed -n '42,95p'

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 2552


🏁 Script executed:

cat -n ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt | sed -n '97,120p'

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1166


🏁 Script executed:

wc -l ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureViewModel.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 172


🏁 Script executed:

cat -n ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureViewModel.kt | head -200

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 8392


🏁 Script executed:

grep -n "onSearchAction\|fun on" ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureViewModel.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 676


🏁 Script executed:

cat -n ./app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureViewModel.kt | tail -150

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 6158


검색 액션이 구현되지 않았습니다.

Line 220의 TODO로 인해 검색 기능이 동작하지 않습니다. ViewModel 핸들러를 연결하고 구현이 필요합니다.

🛠️ 수정 제안(ProcedureScreen/Route 연동)
@@
 fun ProcedureRoute(
@@
     onComplete: () -> Unit,
     viewModel: ProcedureViewModel = hiltViewModel()
 ) {
@@
             ProcedureScreen(
                 uiState = state.data,
                 onExistenceClick = viewModel::onExistenceClick,
                 onWorryClick = viewModel::onWorryClick,
                 onRecoveryOptionClick = viewModel::onRecoveryOptionClick,
                 onYearChange = viewModel::onYearChange,
                 onMonthChange = viewModel::onMonthChange,
                 onDayChange = viewModel::onDayChange,
                 onProcedureCardClick = viewModel::onProcedureCardClick,
+                onSearchAction = viewModel::onSearchAction,
                 onDowntimeClick = viewModel::onDowntimeClick,
@@
 `@Composable`
 fun ProcedureScreen(
     uiState: ProcedureUiState,
     onExistenceClick: (Int) -> Unit,
     onWorryClick: (Long) -> Unit,
     onRecoveryOptionClick: (Int) -> Unit,
     onYearChange: (String) -> Unit,
     onMonthChange: (String) -> Unit,
     onDayChange: (String) -> Unit,
     onProcedureCardClick: (Long) -> Unit,
+    onSearchAction: (String) -> Unit,
     onDowntimeClick: (Long) -> Unit,
@@
                         ProcedureStep.FilteringWithSearch -> {
                             FilteringWithSearchContent(
                                 cardItems = uiState.procedureItems,
                                 selectedCardIds = uiState.selectedProcedureCardIds,
                                 onCardClick = onProcedureCardClick,
-                                onSearchAction = { /* TODO */ },
+                                onSearchAction = onSearchAction,
                                 query = query,
                                 onQueryChange = { query = it },
                                 bottomPadding = uiState.lazyColumnBottomPadding,
                                 modifier = Modifier
                                     .fillMaxWidth()
                                     .padding(horizontal = 24.dp)
                             )
                         }

ViewModel에서 onSearchAction 함수를 구현하고 상태 업데이트 로직을 추가해야 합니다.

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt`
around lines 216 - 223, FilteringWithSearchContent의 onSearchAction이 TODO로 남아 있어
검색 버튼(액션)이 동작하지 않습니다; ProcedureScreen에서 해당 콜백을 ViewModel의 검색 핸들러로 연결하고
ViewModel에 검색 처리 로직을 구현하세요. 구체적으로는 ProcedureScreen의 FilteringWithSearchContent
호출에서 onSearchAction = viewModel::onSearchAction(또는 viewModel.searchProcedures)로
바꾸고, ViewModel에 onSearchAction(query: String) 또는 searchProcedures() 메서드를 추가해
uiState.query를 업데이트하고 procedureItems를 필터링 또는 검색 API 호출로 갱신하도록 상태 업데이트 로직을 구현하세요;
필요한 경우 선택된 카드(uiState.selectedProcedureCardIds)나 페이징/빈 상태 처리도 함께 업데이트하도록 하세요.

Copy link
Copy Markdown
Contributor

@sohee6989 sohee6989 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!

Comment thread app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt Outdated
modifier = Modifier.padding(horizontal = 26.dp)
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p2: 공백 제거!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

저는 가독성 면에서 줄 간 공백이 있는게 나을 것 같아요! 괜찮을까요오옹??
f70227133ba5cb692b2525a39785501f

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

넵넵!
근데 (단순 궁금) 혹시 밑에는 안 띄우셨는데 여기만 띄우신 이유가 있으실까요?!!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ㅎㅎ

Comment on lines +151 to +157
if (uiState.showStepProgressBar) {
StepProgressBar(
totalStep = uiState.totalSteps,
currentStep = uiState.currentStepIndex,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 26.dp)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p1: 이거 프로그레스 바가 없을때 처리 해주셔야 될 것 같아요!
있을 떄 없을 때의 위치 차이가 발생하고 있어요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

소히 언니 저 잘 이해가 안댐. 사진으로 보여주셈.
36a3409c94cda67c3c25c90fa1e8edf8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

수현님꺼에서 알려드리지요오~~

Copy link
Copy Markdown
Contributor Author

@usuuhyn usuuhyn Jan 19, 2026

Choose a reason for hiding this comment

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

패딩값 같은거 확인햇어요 꺄르르 우우 붐따

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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/calendar/navigation/CalendarNavigator.kt`:
- Around line 1-10: CalendarNavigator.kt is missing its package declaration; add
the package line "package com.cherrish.android.presentation.calendar.navigation"
at the top of CalendarNavigator.kt and then update any imports in
MainAppState.kt and MainScreen.kt to reference symbols from that package (e.g.,
import com.cherrish.android.presentation.calendar.navigation.CalendarNavigator
or the specific composable/route symbols you use) so the compiler can resolve
the functions and routes correctly.
- Around line 12-15: Calendar data object is missing the `@Serializable`
annotation which breaks type-safe navigation used by composable<T>; add
`@Serializable` to the Calendar declaration so it matches Procedure (i.e.,
annotate the data object Calendar : MainTabRoute with `@Serializable`) to ensure
both Calendar and Procedure are serializable for composable<T>-based navigation.

In `@app/src/main/java/com/cherrish/android/presentation/main/MainAppState.kt`:
- Around line 20-21: MainAppState imports fail because CalendarNavigator.kt is
missing its package declaration; open CalendarNavigator.kt and add the package
line for com.cherrish.android.presentation.calendar.navigation at the top so the
symbols navigateToCalendar and navigateToProcedure are declared in that package
and MainAppState can import them as
com.cherrish.android.presentation.calendar.navigation.navigateToCalendar and
com.cherrish.android.presentation.calendar.navigation.navigateToProcedure.

Comment thread app/src/main/java/com/cherrish/android/presentation/main/MainAppState.kt Outdated
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt (1)

489-489: Preview 데이터에 오타가 있습니다.

downtimeEndDay의 값이 "2023.08.1"로 되어 있는데, "2023.08.11" 또는 일관된 형식이어야 할 것 같습니다.

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt`:
- Around line 84-88: The DowntimeBottomSheet currently sets
downtimeGuideBubbleText to "" for DowntimeValidationType.INVALID which causes
DowntimeGuideBubble to render an empty bubble; update the logic so that when
validationType == DowntimeValidationType.INVALID (or
downtimeGuideBubbleText.isBlank()) you do not render DowntimeGuideBubble at all.
Locate the downtimeGuideBubbleText assignment and the place where
DowntimeGuideBubble is composed/used and change it to conditionally render the
DowntimeGuideBubble only when the text is non-blank (e.g., check validationType
!= DowntimeValidationType.INVALID or downtimeGuideBubbleText.isNotBlank()) so
the bubble is hidden instead of showing an empty frame.
🧹 Nitpick comments (1)
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt (1)

377-381: NumberPicker가 public으로 선언되어 있습니다.

다른 헬퍼 Composable들은 private으로 선언되어 있는데, NumberPicker만 public입니다. 외부에서 재사용할 계획이 아니라면 private으로 변경하여 일관성을 유지하는 것이 좋습니다.

♻️ 제안
 `@Composable`
-fun NumberPicker(
+private fun NumberPicker(
     list: ImmutableList<Int>,
     state: LazyListState,
     flingBehavior: FlingBehavior,
     modifier: Modifier = Modifier
 ) {

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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt`:
- Around line 31-35: The UI directly calls onNavigateToProcedure on button
clicks instead of routing the event through the ViewModel side-effect pipeline;
update the click handler to call viewModel.onAddButtonClick() so the ViewModel
emits CalendarSideEffect.NavigateToProcedure which is handled by
viewModel.sideEffect.collectLatestSideEffect { ... } that triggers
onNavigateToProcedure(), ensuring the side-effect flow using
CalendarSideEffect.NavigateToProcedure and the ViewModel method
onAddButtonClick() is used consistently.

In
`@app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt`:
- Around line 243-249: The onAddButtonClick function is currently nested inside
loadDowntimeDetail which prevents it from being a callable public member of
CalendarViewModel; move the entire onAddButtonClick declaration out of the
loadDowntimeDetail block to the CalendarViewModel class scope (same level as
other public functions), keep its implementation using viewModelScope.launch and
_sideEffect.emit(CalendarSideEffect.NavigateToProcedure), and ensure its
visibility remains public so CalendarScreen can call
viewModel::onAddButtonClick.
♻️ Duplicate comments (2)
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt (2)

55-57: Loading 및 Failure 상태 처리가 필요합니다.

UiState.LoadingUiState.Failure에서 빈 처리(Unit)로 인해 사용자에게 피드백이 없습니다. 로딩 인디케이터나 에러 UI 표시를 추가해 주세요.


221-221: 검색 액션이 구현되지 않았습니다.

onSearchAction이 TODO로 남아 있어 검색 기능이 동작하지 않습니다. ViewModel 핸들러 연결이 필요합니다.

🧹 Nitpick comments (4)
app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureUiState.kt (2)

221-232: DateTimeFormatter 인스턴스가 매 접근마다 생성됩니다.

downtimeStartDaydowntimeEndDay가 접근될 때마다 DateTimeFormatter.ofPattern("yyyy.MM.dd")가 새로 생성됩니다. Compose recomposition 중 반복 호출 시 불필요한 객체 생성이 발생합니다.

♻️ 수정 제안

companion object에 formatter를 캐싱하세요:

     companion object {
+        private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy.MM.dd")
+
         val FakeNormal = ProcedureUiState(

그리고 프로퍼티에서 재사용:

     val downtimeStartDay: String
         get() {
-            val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd")
-            return LocalDate.now().format(formatter)
+            return LocalDate.now().format(DATE_FORMATTER)
         }

     val downtimeEndDay: String
         get() {
             val target = targetDate ?: return ""
-            val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd")
-            return target.format(formatter)
+            return target.format(DATE_FORMATTER)
         }

177-188: selectedProcedures가 매 접근마다 재계산됩니다.

get() 패턴으로 인해 Composable 내에서 여러 번 접근 시 filter, map, toImmutableList 연산이 반복 수행될 수 있습니다. 현재 리스트 크기가 작아 영향은 미미하지만, 확장성을 고려하면 주의가 필요합니다.

향후 리스트가 커지면 val 초기화 또는 ViewModel에서 미리 계산하여 전달하는 방식을 고려해 주세요.

app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt (1)

129-134: 스크롤 중 과도한 상태 업데이트가 발생할 수 있습니다.

firstVisibleItemIndex가 변경될 때마다 LaunchedEffect가 트리거되어 스크롤 중 매 프레임마다 onDowntimePickerValueChange가 호출될 수 있습니다. 이는 불필요한 recomposition을 유발할 수 있습니다.

♻️ 수정 제안

snapshotFlow를 사용하여 스크롤 완료 후 업데이트하도록 변경:

-    LaunchedEffect(downtimePickerState.firstVisibleItemIndex) {
-        if (uiState.showDowntimeBottomSheet) {
-            val newValue = downtimePickerState.firstVisibleItemIndex + 1
-            onDowntimePickerValueChange(newValue)
-        }
-    }
+    LaunchedEffect(uiState.showDowntimeBottomSheet) {
+        if (uiState.showDowntimeBottomSheet) {
+            snapshotFlow { downtimePickerState.firstVisibleItemIndex }
+                .collect { index ->
+                    onDowntimePickerValueChange(index + 1)
+                }
+        }
+    }

추가로 import androidx.compose.runtime.snapshotFlow 필요.

app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt (1)

36-37: asSharedFlow()를 사용하면 더 안전합니다.

uiState에서 asStateFlow()를 사용한 것처럼 일관성을 위해 asSharedFlow()를 사용하는 것을 권장합니다. 외부에서 실수로 emit하는 것을 방지할 수 있습니다.

♻️ 제안하는 수정사항
     private val _sideEffect = MutableSharedFlow<CalendarSideEffect>()
-    val sideEffect: SharedFlow<CalendarSideEffect> = _sideEffect
+    val sideEffect: SharedFlow<CalendarSideEffect> = _sideEffect.asSharedFlow()

asSharedFlow import 추가:

+import kotlinx.coroutines.flow.asSharedFlow

Comment thread app/src/main/java/com/cherrish/android/presentation/calendar/CalendarViewModel.kt Outdated
Copy link
Copy Markdown
Contributor

@nhyeonii nhyeonii left a comment

Choose a reason for hiding this comment

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

냥냥냥 ~~

Comment on lines +244 to +248
fun onAddButtonClick() {
viewModelScope.launch {
_sideEffect.emit(CalendarSideEffect.NavigateToProcedure)
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 : 허거덩 ㅇㅒ 지금 loadMonthlyCalendar에 잘못 들어가잇다 !! 요거 밖으로 뺴야할거가틍요 ㅜㅜ !!!!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

뺏슈!!!

onCloseClick: () -> Unit,
modifier: Modifier = Modifier
) {
var query by remember { mutableStateOf("") }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 : 요거 query를 상위로 호이스팅 해주느건 어떄요 !?! 아마 시술 검색 텍스트 필드에서 사용하는 것 같은데 query와 onQueryChange를 상태 호이스팅 해주는 것도 좋은거 같아요 ~~

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

조아요!! !!

@usuuhyn
Copy link
Copy Markdown
Contributor Author

usuuhyn commented Jan 19, 2026

소히 언니 구두 어푸 받앗습니당~~~~ 어푸어푸 💦🌊

…-view

# Conflicts:
#	app/src/main/java/com/cherrish/android/presentation/main/MainActivity.kt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FEAT✨ 새로운 기능 구현 수현🍒 수현 담당

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 시술 뷰 UI 구현

3 participants