[Feature] 콜밴 글쓰기 상태 및 뷰모델 추가#1328
[Feature] 콜밴 글쓰기 상태 및 뷰모델 추가#1328JaeYoung290 wants to merge 4 commits intofeature/#1283-callvan-create-screenfrom
Conversation
개요새로운 CallVan 생성 기능의 UI 상태 관리를 위해 상태 데이터 클래스와 ViewModel을 추가합니다. 출발지/도착지 선택, 날짜/시간 설정, 참여자 수 관리, 폼 제출 등의 인터랙션을 Orbit MVI 패턴으로 처리합니다. 변경사항
예상 코드 리뷰 시간🎯 2 (Simple) | ⏱️ ~12분 권장 리뷰어
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
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 |
0446ee2 to
2f28c8d
Compare
4abbee0 to
5a34625
Compare
| val amPmText: String | ||
| get() = if (isAm) "오전" else "오후" | ||
|
|
||
| val participantsText: String | ||
| get() = "$maxParticipants 명" | ||
|
|
||
| val apiDepartureDate: String | ||
| get() = "%04d-%02d-%02d".format(selectedYear, selectedMonth, selectedDay) |
There was a problem hiding this comment.
포맷팅 로직이라 여기 넣었는데 ui단이 나을까요? 재사용성이나 유닛 테스트 시에 더 좋지 않을까 생각되는데 어떤가요
| } | ||
|
|
||
| fun submit() = intent { | ||
| val currentState = state |
There was a problem hiding this comment.
intent의 경우는 비동기이기 때문에 로직이 실행중에도 다른 입력으로 변경될 수 있고 이에 따라 값이 변할 수 있는데 이때 빠르게 조작하면서 생기는 오류를 해결하고자 submit()이 실행될 때의 상태를 저장하도록 했습니다!
예를 들어 사용자가 submit을 누른 후 조작 실수로 다른 장소를 클릭했을 때 저 변수가 없다면 그 장소가 그대로 저장되는 문제가 있습니다
…callvan-create-viewmodel
|
✅ CI 완료. CodeRabbit 리뷰를 요청합니다. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.kt (1)
11-13:Calendar.getInstance()가 3번 호출되어 비효율적입니다.기본값 초기화 시 Calendar 인스턴스를 매번 새로 생성합니다. 날짜가 바뀌는 정확한 시점에 호출되면 year/month/day가 서로 다른 날짜를 참조할 수 있는 엣지 케이스도 존재합니다.
♻️ 수정 제안: companion object에서 기본값 계산
data class CallvanCreateState( val departureLocation: CallvanLocationOption? = null, val arrivalLocation: CallvanLocationOption? = null, val departureCustomText: String? = null, val arrivalCustomText: String? = null, - val selectedYear: Int = Calendar.getInstance().get(Calendar.YEAR), - val selectedMonth: Int = Calendar.getInstance().get(Calendar.MONTH) + 1, - val selectedDay: Int = Calendar.getInstance().get(Calendar.DAY_OF_MONTH), + val selectedYear: Int = DEFAULT_YEAR, + val selectedMonth: Int = DEFAULT_MONTH, + val selectedDay: Int = DEFAULT_DAY, val selectedHour: Int = 12, ... -) { +) { + companion object { + private val calendar = Calendar.getInstance() + private val DEFAULT_YEAR = calendar.get(Calendar.YEAR) + private val DEFAULT_MONTH = calendar.get(Calendar.MONTH) + 1 + private val DEFAULT_DAY = calendar.get(Calendar.DAY_OF_MONTH) + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.kt` around lines 11 - 13, The three default properties selectedYear, selectedMonth, and selectedDay call Calendar.getInstance() separately which is inefficient and can produce inconsistent date parts; compute a single Calendar instance once (e.g., in a companion object or a private local val like now) and derive selectedYear, selectedMonth (+1), and selectedDay from that single instance (update references to selectedYear, selectedMonth, selectedDay in CallvanCreateState to use that single-calendar-derived values).feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateViewModel.kt (1)
148-166: 매직 넘버를 상수로 추출하는 것을 고려해주세요.참가자 수 범위
1과8을 companion object 상수로 추출하면 의미가 명확해지고, 향후 변경 시 유지보수가 용이합니다.♻️ 상수 추출 제안
companion object 추가:
companion object { private const val MIN_PARTICIPANTS = 1 private const val MAX_PARTICIPANTS = 8 }메서드에 적용:
fun decrementParticipants() = blockingIntent { reduce { - if (state.maxParticipants > 1) { + if (state.maxParticipants > MIN_PARTICIPANTS) { state.copy(maxParticipants = state.maxParticipants - 1) } else { state } } } fun incrementParticipants() = blockingIntent { reduce { - if (state.maxParticipants < 8) { + if (state.maxParticipants < MAX_PARTICIPANTS) { state.copy(maxParticipants = state.maxParticipants + 1) } else { state } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateViewModel.kt` around lines 148 - 166, 현재 decrementParticipants와 incrementParticipants에서 사용된 매직 넘버 1과 8을 companion object의 상수로 추출하고 사용하세요: CallvanCreateViewModel에 companion object를 추가하여 private const val MIN_PARTICIPANTS = 1 및 private const val MAX_PARTICIPANTS = 8을 정의하고, decrementParticipants의 조건(state.maxParticipants > MIN_PARTICIPANTS)과 incrementParticipants의 조건(state.maxParticipants < MAX_PARTICIPANTS) 및 상태 복사 시 해당 상수를 사용하도록 수정하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.kt`:
- Around line 14-16: 기본 시간이 현재 자정으로 설정되어 있으므로 CallvanCreateState의 기본값을 정오로 바꾸세요:
selectedHour를 12로 유지하고 isAm를 true에서 false로 변경(또는 AM/PM 플래그를 반전)하여 12:00 PM(정오)을
기본값으로 만들고 selectedMinute는 0으로 유지하도록 CallvanCreateState의 필드(selectedHour,
selectedMinute, isAm)를 업데이트하세요.
- Line 6: The CallvanCreateState data class is missing the `@Immutable` annotation
required by the feature module coding guideline; add the
androidx.compose.runtime.Immutable annotation above the CallvanCreateState
declaration and ensure any list properties inside CallvanCreateState use an
ImmutableList (or other immutable collection) instead of mutable lists so
Compose can optimize correctly.
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateViewModel.kt`:
- Around line 172-186: The call to CreateCallvanPostUseCase is mapping custom
names into departureType/arrivalType; instead pass the actual enum/type into
departureType/arrivalType and supply the custom text to
departureCustomName/arrivalCustomName when the location is OTHER. Update the
call site in CallvanCreateViewModel (the createCallvanPostUseCase invocation)
so: set departureType = currentState.departureLocation!!.type (or
CallvanLocationOption.OTHER.type) and departureCustomName =
currentState.departureCustomText ?: "" when departureLocation == OTHER
(otherwise empty), and likewise set arrivalType =
currentState.arrivalLocation!!.type and arrivalCustomName =
currentState.arrivalCustomText ?: "" when arrivalLocation == OTHER (otherwise
empty), keeping the other params (departureDate, departureTime, maxParticipants)
unchanged.
---
Nitpick comments:
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.kt`:
- Around line 11-13: The three default properties selectedYear, selectedMonth,
and selectedDay call Calendar.getInstance() separately which is inefficient and
can produce inconsistent date parts; compute a single Calendar instance once
(e.g., in a companion object or a private local val like now) and derive
selectedYear, selectedMonth (+1), and selectedDay from that single instance
(update references to selectedYear, selectedMonth, selectedDay in
CallvanCreateState to use that single-calendar-derived values).
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateViewModel.kt`:
- Around line 148-166: 현재 decrementParticipants와 incrementParticipants에서 사용된 매직
넘버 1과 8을 companion object의 상수로 추출하고 사용하세요: CallvanCreateViewModel에 companion
object를 추가하여 private const val MIN_PARTICIPANTS = 1 및 private const val
MAX_PARTICIPANTS = 8을 정의하고, decrementParticipants의 조건(state.maxParticipants >
MIN_PARTICIPANTS)과 incrementParticipants의 조건(state.maxParticipants <
MAX_PARTICIPANTS) 및 상태 복사 시 해당 상수를 사용하도록 수정하세요.
🪄 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: 86a117c4-d9ff-4d43-be86-a8c39e1a9384
📒 Files selected for processing (2)
feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.ktfeature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateViewModel.kt
| import `in`.koreatech.koin.feature.callvan.model.CallvanLocationOption | ||
| import java.util.Calendar | ||
|
|
||
| data class CallvanCreateState( |
There was a problem hiding this comment.
State 클래스에 @Immutable 애노테이션이 누락되었습니다.
코딩 가이드라인에 따르면 feature 모듈의 State 클래스는 Compose 최적화를 위해 @Immutable 애노테이션 사용이 필수입니다.
🛠️ 수정 제안
package `in`.koreatech.koin.feature.callvan.ui.create
import `in`.koreatech.koin.feature.callvan.model.CallvanLocationOption
+import androidx.compose.runtime.Immutable
import java.util.Calendar
+@Immutable
data class CallvanCreateState(As per coding guidelines: "feature/**" - "Compose 최적화를 위해 State 클래스에 @Immutable 및 ImmutableList 사용 필수"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| data class CallvanCreateState( | |
| package `in`.koreatech.koin.feature.callvan.ui.create | |
| import `in`.koreatech.koin.feature.callvan.model.CallvanLocationOption | |
| import androidx.compose.runtime.Immutable | |
| import java.util.Calendar | |
| `@Immutable` | |
| data class CallvanCreateState( |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.kt`
at line 6, The CallvanCreateState data class is missing the `@Immutable`
annotation required by the feature module coding guideline; add the
androidx.compose.runtime.Immutable annotation above the CallvanCreateState
declaration and ensure any list properties inside CallvanCreateState use an
ImmutableList (or other immutable collection) instead of mutable lists so
Compose can optimize correctly.
| val selectedHour: Int = 12, | ||
| val selectedMinute: Int = 0, | ||
| val isAm: Boolean = true, |
There was a problem hiding this comment.
기본 시간이 자정(12:00 AM)으로 설정되어 있습니다.
selectedHour = 12와 isAm = true 조합은 자정(00:00)을 의미합니다. 콜밴 예약의 기본값으로는 정오(12:00 PM)가 더 적합할 수 있습니다.
💡 정오를 기본값으로 하려면
val selectedHour: Int = 12,
val selectedMinute: Int = 0,
- val isAm: Boolean = true,
+ val isAm: Boolean = false,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| val selectedHour: Int = 12, | |
| val selectedMinute: Int = 0, | |
| val isAm: Boolean = true, | |
| val selectedHour: Int = 12, | |
| val selectedMinute: Int = 0, | |
| val isAm: Boolean = false, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateState.kt`
around lines 14 - 16, 기본 시간이 현재 자정으로 설정되어 있으므로 CallvanCreateState의 기본값을 정오로
바꾸세요: selectedHour를 12로 유지하고 isAm를 true에서 false로 변경(또는 AM/PM 플래그를 반전)하여 12:00
PM(정오)을 기본값으로 만들고 selectedMinute는 0으로 유지하도록 CallvanCreateState의 필드(selectedHour,
selectedMinute, isAm)를 업데이트하세요.
| createCallvanPostUseCase( | ||
| departureType = if (currentState.departureLocation == CallvanLocationOption.OTHER) { | ||
| currentState.departureCustomText ?: "" | ||
| } else { | ||
| currentState.departureLocation!!.type | ||
| }, | ||
| arrivalType = if (currentState.arrivalLocation == CallvanLocationOption.OTHER) { | ||
| currentState.arrivalCustomText ?: "" | ||
| } else { | ||
| currentState.arrivalLocation!!.type | ||
| }, | ||
| departureDate = currentState.apiDepartureDate, | ||
| departureTime = currentState.apiDepartureTime, | ||
| maxParticipants = currentState.maxParticipants | ||
| ).onSuccess { post -> |
There was a problem hiding this comment.
UseCase 호출 시 파라미터 매핑이 잘못되었습니다.
CreateCallvanPostUseCase의 시그니처를 확인하면 departureCustomName과 arrivalCustomName이 별도의 파라미터로 존재합니다. 현재 코드는 OTHER 위치 타입일 때 customText를 departureType에 직접 전달하고 있어 API 호출이 올바르지 않습니다.
domain/src/main/java/in/koreatech/koin/domain/usecase/callvan/CreateCallvanPostUseCase.kt의 시그니처:
departureType: 위치 타입 (예: "KOREATECH", "OTHER" 등)departureCustomName: OTHER일 때의 커스텀 이름
🐛 수정 제안
createCallvanPostUseCase(
- departureType = if (currentState.departureLocation == CallvanLocationOption.OTHER) {
- currentState.departureCustomText ?: ""
- } else {
- currentState.departureLocation!!.type
- },
- arrivalType = if (currentState.arrivalLocation == CallvanLocationOption.OTHER) {
- currentState.arrivalCustomText ?: ""
- } else {
- currentState.arrivalLocation!!.type
- },
+ departureType = currentState.departureLocation!!.type,
+ departureCustomName = if (currentState.departureLocation == CallvanLocationOption.OTHER) {
+ currentState.departureCustomText
+ } else {
+ null
+ },
+ arrivalType = currentState.arrivalLocation!!.type,
+ arrivalCustomName = if (currentState.arrivalLocation == CallvanLocationOption.OTHER) {
+ currentState.arrivalCustomText
+ } else {
+ null
+ },
departureDate = currentState.apiDepartureDate,
departureTime = currentState.apiDepartureTime,
maxParticipants = currentState.maxParticipants
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@feature/callvan/src/main/java/in/koreatech/koin/feature/callvan/ui/create/CallvanCreateViewModel.kt`
around lines 172 - 186, The call to CreateCallvanPostUseCase is mapping custom
names into departureType/arrivalType; instead pass the actual enum/type into
departureType/arrivalType and supply the custom text to
departureCustomName/arrivalCustomName when the location is OTHER. Update the
call site in CallvanCreateViewModel (the createCallvanPostUseCase invocation)
so: set departureType = currentState.departureLocation!!.type (or
CallvanLocationOption.OTHER.type) and departureCustomName =
currentState.departureCustomText ?: "" when departureLocation == OTHER
(otherwise empty), and likewise set arrivalType =
currentState.arrivalLocation!!.type and arrivalCustomName =
currentState.arrivalCustomText ?: "" when arrivalLocation == OTHER (otherwise
empty), keeping the other params (departureDate, departureTime, maxParticipants)
unchanged.
PR 개요
이슈 번호: #1283
PR 체크리스트
작업사항
작업사항의 상세한 설명
콜밴 글쓰기 화면의 viewModel을 추가합니다.
CallvanCreateState: 위치·날짜·시간·인원·피커 가시성 등 UI 상태 정의CallvanCreateViewModel논의 사항
스크린샷
추가내용
Summary by CodeRabbit
새로운 기능