Spm 130#17
Conversation
Walkthrough출고(Outbound) 라우트를 도입해 기존 Delivery 라우트를 대체하고, 출고·장바구니 기능(네트워크 DTO/API, 리포지토리, 유스케이스, DI, ViewModel, UI)과 부품 상세 바텀시트를 전층에 추가·연결했습니다. 공통 버튼 변형·문자열·리소스·소소한 로그 리팩터링도 포함됩니다. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant App as AppNavHost
participant OutboundScreen as OutboundListScreen
participant OutboundVM as OutboundListViewModel
participant UseCase as GetOutboundUseCase
participant Repo as OutboundRepository
participant API as OutboundApi
participant Server
User->>App: 하단 탭 선택 (출고)
App->>OutboundScreen: 라우팅 -> ROUTE_OUTBOUND
OutboundScreen->>OutboundVM: bindLabel / Load
OutboundVM->>UseCase: invoke()
UseCase->>Repo: getOutboundList()
Repo->>API: GET agency/1/outbound
API->>Server: 요청
Server-->>API: ApiResponse<List<OutboundDto>>
API-->>Repo: DTO 전달
Repo->>Repo: dto.toModel()
Repo-->>UseCase: OutboundList
UseCase-->>OutboundVM: OutboundList
OutboundVM-->>OutboundScreen: uiState 업데이트
OutboundScreen->>User: 목록 렌더링
sequenceDiagram
actor User
participant PartList as PartListScreen
participant PartVM as PartListViewModel
participant Bottom as PartDetailBottomSheet
participant DetailVM as PartDetailViewModel
participant AddOutbound as AddOutboundUseCase
participant OutRepo as OutboundRepository
participant OutAPI as OutboundApi
participant Server
User->>PartList: 부품 카드 클릭
PartList->>PartVM: ShowBottomSheet(part)
PartVM-->>PartList: selectedPart 설정
PartList->>Bottom: ModalBottomSheet 열기 (part)
Bottom->>DetailVM: Initialize / bindLabel
User->>Bottom: 수량 설정 및 '출고목록에 추가' 클릭
Bottom->>DetailVM: AddToOutbound(partId, qty)
DetailVM->>AddOutbound: invoke(partId, qty)
AddOutbound->>OutRepo: addOutbound(...)
OutRepo->>OutAPI: POST agency/1/outbound
OutAPI->>Server: 요청
Server-->>OutAPI: ApiSuccessResponse
OutAPI-->>OutRepo: 응답
OutRepo-->>AddOutbound: Result<Unit>
AddOutbound-->>DetailVM: 결과
DetailVM-->>Bottom: isOutboundSuccess 업데이트
Bottom->>User: 성공 토스트 / 다이얼로그 닫기
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60-75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
🔇 Additional comments (3)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 19
🧹 Nitpick comments (26)
app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
3-3: 사용되지 않는 import 제거
android.R.attr.enabled는 파일 어디에서도 사용되지 않습니다. 이 import를 제거하세요.-import android.R.attr.enabledapp/src/main/java/com/sampoom/android/feature/cart/domain/model/CartList.kt (1)
3-11: 래퍼 클래스 설계 고려사항
totalCount와isEmpty는 단순히items.size와items.isEmpty()를 래핑하는 derived 속성입니다. 추가적인 비즈니스 로직이나 불변성 보장이 필요하지 않다면, 도메인 레이어에서List<Cart>를 직접 사용하는 것도 고려해볼 수 있습니다.다만 페이지네이션이나 메타데이터 추가를 위한 확장성을 고려한 설계라면 현재 구현이 적절합니다.
app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/UpdateCartRequestDto.kt (1)
1-5: 장바구니 수량 업데이트 DTO 구현 확인DTO 구현은 적절하나,
UpdateOutboundRequestDto와 구조가 동일합니다. 현재는 모듈 경계를 유지하는 것이 합리적이지만, 향후 공통 DTO(예:UpdateQuantityRequestDto)를 core 모듈로 추출하여 중복을 줄이는 것을 고려해볼 수 있습니다.app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt (1)
371-394: 주석 처리된 코드를 제거하세요.24줄에 걸친 주석 처리된
OutlinedTextField코드는 버전 관리 시스템에서 확인할 수 있으므로 제거하는 것이 좋습니다. 코드베이스를 깔끔하게 유지하는 데 도움이 됩니다.이 코드가 나중에 필요하다면, Git 히스토리에서 복원할 수 있습니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt (1)
6-10: 에러 처리 방식의 일관성을 고려하세요.
getCartList()는CartList를 직접 반환하지만 (예외를 던질 수 있음), 다른 메서드들은Result<Unit>을 반환합니다. 이러한 비일관성으로 인해 호출자가getCartList()에는 try-catch를, 다른 메서드에는 Result 처리를 사용해야 합니다.일관성을 위해
getCartList()도Result<CartList>를 반환하도록 변경하는 것을 고려해보세요:interface CartRepository { suspend fun getCartList(): Result<CartList> suspend fun addCart(partId: Long, quantity: Long): Result<Unit> suspend fun deleteCart(cartItemId: Long): Result<Unit> suspend fun deleteAllCart(): Result<Unit> suspend fun updateCartQuantity(cartItemId: Long, quantity: Long): Result<Unit> }이렇게 하면 모든 메서드에서 일관된 에러 처리 패턴을 사용할 수 있습니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt (1)
64-67: 사용되지 않는 변수를 제거하세요.
scope변수가 선언되었지만 코드 내에서 사용되지 않습니다.rememberCoroutineScope()와scope변수 선언을 제거할 수 있습니다.다음 diff를 적용하여 사용되지 않는 변수를 제거하세요:
// ModalBottomSheet 상태 관리 val sheetState = rememberModalBottomSheetState() - val scope = rememberCoroutineScope() var showBottomSheet by remember { mutableStateOf(false) }app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt (1)
5-15: 상태 플래그 분산 정리와 선택 상태 사용 여부 확인 제안
- isUpdating/isDeleting/isOrderSuccess와 개별 에러 필드(cartError/updateError/deleteError)가 분산되어 있어 관리 비용이 큽니다. 단일 OperationState(Idle/Loading/Success/Failure)로 합치거나, 작업별 소형 상태 구조체로 묶는 방식을 권장합니다. 일회성 성공 신호(isOrderSuccess)는 Event/Channel(또는 one‑shot effect)로 처리하면 중복 토스트/재렌더를 줄일 수 있습니다.
- selectedCart가 실제로 사용되지 않으면 제거해 상태 오염을 줄이는 것이 좋습니다. 사용 중이라면 주석/도큐먼트로 목적을 명시해 주세요.
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt (1)
3-12: 수량 유효성(1 이상) 보장 장치 추가 권장UpdateQuantity.quantity가 0/음수로 전달될 수 있습니다. ViewModel/Reducer에서 require(quantity > 0)로 방어하거나, 가능하다면 @IntRange(from = 1) 주석(또는 KDoc로 계약 명시)으로 의도를 구체화해 주세요. 도메인에서 Long을 유지해야 한다면 주석 기반 계약이라도 명확히 하는 편이 좋습니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt (1)
5-11: 에러 처리 일관성 및 연산 안전성 정렬 권장
- 반환형이 혼합(getOutboundList는 예외, 나머지는 Result)되어 호출부 에러 처리 정책이 일관되지 않습니다. 전부 Result로 통일하거나(예: Result) 전부 예외 전파로 맞추는 방식 중 하나로 정렬해 주세요.
- processOutbound/deleteAllOutbound는 재시도 시 중복 처리 위험이 있습니다. 구현부에 idempotencyKey/서버 멱등 보장 또는 클라이언트 측 재시도/백오프 정책을 명시하는 것이 안전합니다. 최소한 KDoc로 계약을 남겨 주세요.
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt (1)
84-104: 중복 제출 방지(이중 탭/빠른 연타) 가드 제안외부 호출이 비동기라 isUpdating 플래그가 UI에 반영되기 전 중복 호출될 수 있습니다. 안전을 위해 함수 초입 가드 또는 클릭 스로틀을 추가해 주세요.
예:
private fun addToOutbound(partId: Long, quantity: Long) { if (_uiState.value.isUpdating) return // ... }Also applies to: 105-124
app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt (1)
52-55: 네이밍 일관성: Delivery → Outbound로 리네이밍 고려UI 라벨/아이콘은 변경됐으나 클래스명은 BottomNavItem.Delivery로 남아 있습니다. 장기적으로는 BottomNavItem.Outbound로 변경해 의미를 통일하는 편이 가독성에 좋습니다.
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt (4)
3-3: 불필요/오입력된 import 제거 권장android.R.attr.onClick, shadow, OutboundListUiEvent, kotlin.collections.forEach 모두 미사용입니다. 빌드/린트 노이즈를 줄이기 위해 제거해 주세요.
-import android.R.attr.onClick - import androidx.compose.ui.draw.shadow - import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent - import kotlin.collections.forEachAlso applies to: 32-32, 50-51
72-81: 성공 상태 초기화 위치 조정isOrderSuccess가 false일 때도 clearSuccess가 호출됩니다. 불필요한 상태 업데이트/재구독을 유발할 수 있습니다. if 블록 내부로 이동해 주세요.
LaunchedEffect(uiState.isOrderSuccess) { - if (uiState.isOrderSuccess) { - Toast.makeText( - context, - context.getString(R.string.cart_toast_order_text), - Toast.LENGTH_SHORT - ).show() - } - viewModel.clearSuccess() + if (uiState.isOrderSuccess) { + Toast.makeText( + context, + context.getString(R.string.cart_toast_order_text), + Toast.LENGTH_SHORT + ).show() + viewModel.clearSuccess() + } }
163-176: LazyColumn: forEach+item 대신 items 사용 및 key 제공현재 forEach로 item을 감싸 렌더링하고 있어 키 관리가 어렵고 스크롤/상태 보존 이슈가 생길 수 있습니다. items API와 key를 사용해 주세요.
- uiState.cartList.forEach { category -> - category.groups.forEach { group -> - item { - CartSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts, - isUpdating = uiState.isUpdating, - isDeleting = uiState.isDeleting, - onEvent = { viewModel.onEvent(it) } - ) - } - } - } + items( + items = uiState.cartList, + key = { it.categoryName } // 필요 시 고유 ID로 교체 + ) { category -> + items( + items = category.groups, + key = { it.groupName } // 필요 시 고유 ID로 교체 + ) { group -> + CartSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + isUpdating = uiState.isUpdating, + isDeleting = uiState.isDeleting, + onEvent = { viewModel.onEvent(it) } + ) + } + }
157-162: 리스트 하단 패딩으로 버튼과 겹침 방지하단 Spacer 아이템 대신 LazyColumn의 contentPadding을 사용하고, 버튼 쪽은 navigationBarsPadding을 적용하면 기기별 안전영역을 자동 처리합니다.
LazyColumn( modifier = Modifier .fillMaxSize() - .padding(horizontal = 16.dp), + .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) + verticalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = PaddingValues(bottom = 96.dp) ) { - item { Spacer(Modifier.height(100.dp)) } } CommonButton( modifier = Modifier .fillMaxWidth() .align(Alignment.BottomEnd) - .padding(16.dp) - .padding(end = 72.dp), + .padding(16.dp) + .navigationBarsPadding(),Also applies to: 177-177, 181-186
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (2)
4-4: 미사용 import 정리android.util.Log.v는 미사용입니다. 제거해 주세요.
-import android.util.Log.v
45-46: 네이밍 정합성(nit)processOutBound → processOutbound 로 메서드명을 통일하면 가독성이 좋아집니다.
app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt (1)
17-41: 엔드포인트 내 agency/1 하드코딩 확인 요청멀티 에이전시 지원 계획이 있다면 path 파라미터/인터셉터 등으로 치환 가능하도록 고려해 주세요. 단일 테넌트라면 무시해도 됩니다.
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (1)
98-98: 로그 태그 오타(nit)"OutboundListViewModel" → "CartListViewModel".
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt (6)
71-77: 성공 상태 초기화 위치 조정 (2곳)성공이 아닐 때도 clearSuccess가 호출됩니다. if 내부에서만 호출해 불필요한 상태 변경을 줄이세요.
LaunchedEffect(uiState.isOutboundSuccess) { - if (uiState.isOutboundSuccess) { - Toast.makeText(context, context.getString(R.string.outbound_toast_success), Toast.LENGTH_SHORT).show() - } - viewModel.clearSuccess() + if (uiState.isOutboundSuccess) { + Toast.makeText(context, context.getString(R.string.outbound_toast_success), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() + } } LaunchedEffect(uiState.isCartSuccess) { - if (uiState.isCartSuccess) { - Toast.makeText(context, context.getString(R.string.cart_toast_success), Toast.LENGTH_SHORT).show() - } - viewModel.clearSuccess() + if (uiState.isCartSuccess) { + Toast.makeText(context, context.getString(R.string.cart_toast_success), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() + } }Also applies to: 79-86
35-35: 미사용 import 정리Preview, delay 미사용입니다. 제거해 주세요.
-import androidx.compose.ui.tooling.preview.Preview -import kotlinx.coroutines.delayAlso applies to: 45-45
121-125: 수량 표기 문자열 국제화 개선문자열 연결 대신 stringResource 포맷을 사용해 간격/현지화 문제를 방지하세요. 예: "현재 수량: %d개"
Text(stringResource(R.string.part_current_quantity_format, part.quantity))(리소스에 형식 문자열 추가 필요)
150-175: 업데이트 중 입력 비활성화로딩 중에도 수량 입력이 가능하여 레이스/UX 혼선이 생길 수 있습니다. OutlinedTextField에 enabled 플래그를 적용하세요.
OutlinedTextField( value = uiState.quantity.toString(), onValueChange = { newValue -> /* ... */ }, modifier = Modifier.width(100.dp), singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), textStyle = MaterialTheme.typography.titleMedium.copy(textAlign = TextAlign.Center), + enabled = !uiState.isUpdating, colors = OutlinedTextFieldDefaults.colors(
198-203: 아이콘 접근성(nit)장식 목적이 아니라 버튼 의미 전달 용도라면 contentDescription을 제공하거나 click 영역에 의미 텍스트가 있는지 확인해 주세요. 현재는 null입니다.
Also applies to: 210-211
72-85: 성공 시 BottomSheet 닫기 여부 확인주석과 달리 onDismiss 호출이 없어 시트가 유지됩니다. 성공 시 onDismiss() 호출 여부를 제품 기획에 맞춰 결정해 주세요.
app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt (1)
20-59: 도메인 특화 예외를 사용하는 것을 권장합니다.현재 모든 에러 처리에서 제네릭
Exception을 사용하고 있습니다. 더 명확한 에러 처리와 디버깅을 위해 도메인 특화 예외(예:OutboundException,OutboundApiException등)를 정의하여 사용하는 것을 고려해보세요.예시:
sealed class OutboundException(message: String) : Exception(message) { class ApiException(message: String) : OutboundException(message) class NetworkException(message: String) : OutboundException(message) }그런 다음
throw Exception(dto.message)대신throw OutboundException.ApiException(dto.message)를 사용할 수 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (53)
app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt(4 hunks)app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt(1 hunks)app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt(1 hunks)app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt(4 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/AddCartRequestDto.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/UpdateCartRequestDto.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/model/CartList.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/AddOutboundRequestDto.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/UpdateOutboundRequestDto.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/di/OutboundModules.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/model/OutboundList.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt(4 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt(1 hunks)app/src/main/res/drawable/delete.xml(1 hunks)app/src/main/res/values/strings.xml(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt (5)
app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt (3)
textColor(256-257)backgroundCardColor(253-254)textSecondaryColor(259-260)app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt (1)
ErrorContent(18-37)app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt (1)
EmptyContent(9-20)app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
CommonButton(49-176)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (1)
onEvent(41-52)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt (5)
app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt (3)
textColor(256-257)backgroundCardColor(253-254)textSecondaryColor(259-260)app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt (1)
ErrorContent(18-37)app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt (1)
EmptyContent(9-20)app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
CommonButton(49-176)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (1)
onEvent(38-49)
app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt (2)
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt (1)
OutboundListScreen(68-253)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt (1)
CartListScreen(53-242)
app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt (3)
disableColor(262-263)textColor(256-257)textSecondaryColor(259-260)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (4)
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (4)
updateQuantity(104-124)updateLocalQuantity(126-145)removeFromLocalList(191-210)removeAllFromLocalList(212-216)app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt (2)
deleteCart(25-26)deleteAllCart(36-37)app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt (2)
deleteCart(30-35)deleteAllCart(37-42)app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt (2)
deleteCart(8-8)deleteAllCart(9-9)
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt (2)
app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt (2)
textColor(256-257)textSecondaryColor(259-260)app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
CommonButton(49-176)
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (4)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (4)
updateQuantity(102-122)updateLocalQuantity(124-143)removeFromLocalList(189-208)removeAllFromLocalList(210-214)app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt (2)
deleteOutbound(29-30)deleteAllOutbound(40-41)app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt (2)
deleteOutbound(37-42)deleteAllOutbound(44-49)app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt (2)
deleteOutbound(9-9)deleteAllOutbound(10-10)
app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt (1)
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt (1)
PartDetailBottomSheet(47-274)
🔇 Additional comments (59)
app/src/main/res/drawable/delete.xml (1)
1-9: LGTM!벡터 드로어블 리소스가 올바르게 정의되었습니다. 25x25 dp 크기는 UI 아이콘으로 적절하고, @color/white 리소스 참조를 사용하여 테마 기반 색상 변경이 가능하도록 설계되었습니다. 휴지통 아이콘 경로 데이터도 명확하고 표준적인 형태입니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt (2)
1-5: 패키지 구조와 import가 적절합니다.패키지명과 필요한 의존성들이 올바르게 선언되어 있습니다.
6-10: 백엔드 검증에 의존하는 현재 설계가 의도된 것임을 확인했습니다.검증 결과:
- UseCase, Repository, API, DTO 어디에도 클라이언트 측 입력 검증이 없습니다
Result<Unit>반환 타입과 ViewModel의onFailure처리를 통해 백엔드 에러를 적절히 전파합니다이 설계는 백엔드에서
dto.success플래그와 메시지로 검증을 담당하도록 의도되었으며, 모던 Android 아키텍처에서 일반적인 패턴입니다. 다만, 백엔드 API에서quantity > 0, 유효한cartItemId등의 검증이 제대로 구현되어 있는지 확인해 주세요.app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
158-174: 새로운 Error variant 구현이 적절합니다Error variant가 다른 variant들과 일관된 패턴으로 구현되었으며, FailRed와 White 색상 조합이 오류 상태를 나타내기에 적합합니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt (1)
1-21: 도메인 모델 구현이 깔끔합니다Cart, CartGroup, CartPart의 3계층 구조가 명확하고 불변 데이터 클래스로 적절히 구현되었습니다.
참고: 파일 끝에 개행 문자를 추가하는 것이 Kotlin 스타일 가이드에 부합합니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt (1)
1-21: 도메인 모델이 Cart 모델과 일관성 있게 구현되었습니다Outbound, OutboundGroup, OutboundPart의 구조가 Cart 도메인 모델과 동일한 패턴을 따르고 있어 코드베이스 전반의 일관성이 유지됩니다.
참고: 파일 끝에 개행 문자를 추가하는 것이 좋습니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/model/OutboundList.kt (1)
3-11: CartList와 일관된 패턴 사용OutboundList가 CartList와 동일한 패턴(derived 속성, empty() 팩토리)을 따르고 있어 코드베이스 전반의 일관성이 유지됩니다. 두 도메인에서 동일한 접근 방식을 사용하는 것이 유지보수성에 도움이 됩니다.
app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt (1)
3-21: 서버 API 응답 형식에 대한 검증 필요검증 결과 다음이 확인되었습니다:
- FieldNamingPolicy.IDENTITY 설정: NetworkModule.kt:36에서 정확히 구성되어 있음 (리뷰어의 기술적 판단이 정확함)
- @SerializedName 미사용: 전체 코드베이스에서 @SerializedName 어노테이션이 사용되지 않음 (OutboundDto 및 유사 DTO들 모두 해당)
- 파일 끝 개행: OutboundDto.kt의 마지막이 개행 문자 없이 ")"로 종료됨 (리뷰어의 지적이 정확함)
남은 검증 사항: 서버 API가 실제로 camelCase(현재 DTO 필드명)를 반환하는지, 아니면 snake_case를 반환하는지 코드베이스에서 확인할 수 없습니다. 테스트 픽스처나 API 문서, 또는 실제 응답 샘플이 없기 때문입니다.
리뷰어의 우려가 유효하려면 서버 API 문서나 응답 샘플을 통해 필드명 형식을 직접 확인하고, 필요시
@SerializedName어노테이션을 추가해야 합니다.app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt (1)
36-36: 리뷰 코멘트는 잘못된 가정에 기반함이 PR에서
NetworkModule.kt이 변경되지 않았습니다. NetworkModule.kt의FieldNamingPolicy는 이미IDENTITY로 설정되어 있었고, 이 커밋에서 어떤 변경도 발생하지 않았습니다.따라서 리뷰 코멘트에서 언급한 "LOWER_CASE_WITH_UNDERSCORES에서 IDENTITY로의 변경"은 실제로 발생하지 않았으며, 새로 추가된 DTO들(CartDto, OutboundDto)은 기존의 IDENTITY 정책에 이미 맞춰져 있습니다.
Likely an incorrect or invalid review comment.
app/src/main/res/values/strings.xml (4)
51-57: 부품 조회 Bottom Sheet 문자열 리소스 추가 확인부품 상세 바텀시트에 필요한 모든 문자열 리소스가 적절하게 정의되어 있습니다.
59-68: 출고 목록 문자열 리소스 추가 확인출고 기능에 필요한 모든 UI 텍스트가 체계적으로 정의되어 있습니다.
70-79: 장바구니 문자열 리소스 추가 확인장바구니 기능에 필요한 모든 UI 텍스트가 일관성 있게 정의되어 있습니다.
84-89: 공통 문자열 리소스 추가 확인여러 기능에서 재사용 가능한 공통 액션 문자열들이 적절하게 추가되었습니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt (1)
43-44: 바텀시트 이벤트 핸들링 구현 확인바텀시트 표시/숨김 처리가 명확하고 올바르게 구현되었습니다. 상태 업데이트 로직이 간결하며 부작용이 없습니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt (1)
1-10: 출고목록 전체 삭제 유스케이스 구현 확인표준 유스케이스 패턴을 따르는 깔끔한 구현입니다. 도메인 레이어의 책임 분리가 적절합니다.
app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/UpdateOutboundRequestDto.kt (1)
1-5: 출고 수량 업데이트 DTO 구현 확인API 요청 페이로드로 적절한 간단한 데이터 클래스입니다.
app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/AddCartRequestDto.kt (1)
1-6: 장바구니 추가 DTO 구현 확인장바구니에 부품을 추가하는 데 필요한 필드들이 적절하게 정의된 깔끔한 데이터 클래스입니다.
app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt (1)
10-14: 데이터 반환이 없는 API 응답 타입 추가 확인데이터 페이로드가 없는 성공/실패 응답을 위한
ApiSuccessResponse타입이 적절하게 추가되었습니다. 삭제, 업데이트 등의 작업에 유용한 설계입니다.app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt (1)
9-9: 부품 선택 상태 필드 추가 확인바텀시트에서 표시할 선택된 부품을 추적하기 위한
selectedPart필드가 적절하게 추가되었습니다. nullable 타입과 null 기본값이 적절합니다.app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt (1)
3-9: 바텀시트 이벤트 정의가 명확합니다!Part 객체를 전달하는
ShowBottomSheet와 해제를 위한DismissBottomSheet이벤트가 타입 안전하게 정의되어 있으며, 기존 이벤트 패턴과 일관성 있게 구현되었습니다.app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/AddOutboundRequestDto.kt (1)
3-6: DTO 구현이 간결합니다.
partId와quantity모두Long타입으로 정의되어 있습니다.quantity의 경우 일반적으로Int타입으로도 충분한 경우가 많은데, 매우 큰 수량을 다룰 필요가 있어Long을 선택하셨는지 확인해 주세요.app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt (1)
1-10: 유스케이스 구현이 올바릅니다!표준 유스케이스 패턴을 따르며,
OutboundRepository에 대한 의존성이 적절히 주입되고deleteOutbound작업이 깔끔하게 위임되었습니다.app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt (1)
1-10: 유스케이스 구현이 올바릅니다!출고 아이템 추가를 위한 유스케이스가 표준 패턴에 따라 구현되었으며, 리포지토리로의 위임이 적절합니다. 다른 유스케이스들과 일관성 있는 구조입니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt (1)
1-10: 유스케이스 구현이 올바릅니다!장바구니 전체 삭제 기능이 적절히 구현되었습니다. 리포지토리에 대한 의존성 주입과 위임이 올바르게 처리되었습니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt (1)
1-10: 유스케이스 구현이 올바릅니다!개별 장바구니 아이템 삭제 유스케이스가 표준 패턴을 따라 구현되었으며, 출고 기능의 유사한 유스케이스와 일관성 있는 구조를 유지하고 있습니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt (1)
1-10: 유스케이스 구현이 올바릅니다!출고 목록 조회 유스케이스가 깔끔하게 구현되었습니다. 리포지토리로부터 데이터를 가져오는 로직이 적절히 위임되었습니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt (1)
1-10: 유스케이스 구현이 올바릅니다!장바구니 목록 조회 유스케이스가 표준 패턴을 따라 구현되었으며, 출고 기능의
GetOutboundUseCase와 동일한 구조로 일관성을 유지하고 있습니다.app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt (1)
10-12: 깔끔한 매퍼 구현입니다.DTO에서 도메인 모델로의 변환 로직이 명확하고 간결합니다. 중첩된 컬렉션 매핑도 적절하게 처리되었습니다.
app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt (1)
15-27: DI 설정이 올바르게 구성되었습니다.Hilt의 모듈 구성이 표준 패턴을 잘 따르고 있으며, Repository와 API의 바인딩이 적절합니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt (1)
6-10: 표준 유스케이스 패턴을 잘 따르고 있습니다.Repository로의 깔끔한 위임과 간결한 구현이 좋습니다.
app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt (1)
10-12: Cart 매퍼와 일관된 구조입니다.DTO에서 도메인 모델로의 변환이 명확하고, 코드베이스 전반에 걸쳐 일관성을 유지하고 있습니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt (1)
5-12: UI 상태 관리가 잘 설계되었습니다.적절한 기본값 설정과 nullable 타입 사용으로 다양한 UI 상태를 효과적으로 표현하고 있습니다.
app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt (1)
3-21: JSON 직렬화 필드명을 확인하세요.DTO에
@SerializedName어노테이션이 없으므로, 백엔드 API가camelCase를 사용해야 정상 작동합니다. 만약 백엔드가snake_case를 사용한다면 직렬화가 실패할 수 있습니다.백엔드 API 응답 형식을 확인하고, 필요한 경우 다음과 같이 어노테이션을 추가하세요:
data class CartDto( @SerializedName("category_id") val categoryId: Long, @SerializedName("category_name") val categoryName: String, val groups: List<CartGroupDto> )app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt (2)
79-93: LaunchedEffect 로직을 검토하세요.Line 79-81의
LaunchedEffect(Unit)에서clearSuccess()를 호출하고, line 88-93에서도 다시 호출합니다. 또한isOrderSuccess가 true인 상태로 유지되면 리컴포지션마다 Toast가 반복 표시될 수 있습니다.
isOrderSuccess가 이벤트 발생 후 즉시 false로 리셋되는지 확인하세요. 그렇지 않으면 다음과 같이 수정하는 것을 고려하세요:LaunchedEffect(uiState.isOrderSuccess) { if (uiState.isOrderSuccess) { Toast.makeText(context, context.getString(R.string.outbound_toast_order_text), Toast.LENGTH_SHORT).show() viewModel.clearSuccess() } } // 중복 clearSuccess 호출 제거 LaunchedEffect(Unit) { // clearSuccess() 제거 }
95-204: 전반적인 UI 구현이 잘 되어 있습니다.로딩, 에러, 빈 목록, 데이터 표시 등 다양한 UI 상태를 적절하게 처리하고 있으며, AlertDialog를 통한 사용자 확인 플로우도 잘 구현되어 있습니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt (3)
130-136: LGTM!부품 아이템 클릭 시 이벤트 발행과 바텀시트 표시 로직이 올바르게 구현되었습니다.
143-161: LGTM!바텀시트 구현이 올바르게 되어 있습니다.
selectedPart에 대한 null 체크와 해제 로직이 적절합니다.
164-210: LGTM!
PartListItemCard에 클릭 핸들러가 올바르게 추가되었습니다.app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt (5)
14-18: API 호출 실패 시 예외 처리를 확인하세요.
getCartList()메서드는 다른 메서드들과 달리runCatching으로 감싸지 않고 직접 결과를 반환합니다. API 호출이 실패할 경우 처리되지 않은 예외가 발생할 수 있습니다. 리포지토리 인터페이스에서Result<CartList>를 반환하도록 의도했는지, 아니면 예외를 상위 레이어로 전파하는 것이 의도된 동작인지 확인해주세요.
20-28: LGTM!장바구니 추가 로직이 올바르게 구현되었습니다. 에러 처리가 적절합니다.
30-35: LGTM!장바구니 항목 삭제 로직이 올바르게 구현되었습니다.
37-42: LGTM!전체 장바구니 비우기 로직이 올바르게 구현되었습니다.
44-52: LGTM!수량 업데이트 로직이 올바르게 구현되었습니다.
app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt (1)
6-10: LGTM!출고 처리 UseCase가 올바르게 구현되었습니다. 리포지토리에 직접 위임하는 간단한 구조입니다.
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt (1)
5-15: LGTM!출고 목록 UI 상태가 잘 정의되었습니다. 로딩, 에러, 선택, 업데이트, 삭제 등 필요한 모든 상태를 포함하고 있습니다.
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt (1)
3-12: LGTM!장바구니 UI 이벤트가 잘 정의되었습니다. 필요한 모든 사용자 액션과 에러 처리 이벤트가 포함되어 있습니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt (1)
5-14: LGTM!부품 상세 UI 이벤트가 잘 정의되었습니다. 초기화, 수량 조정, 출고/장바구니 추가 등 필요한 모든 이벤트가 포함되어 있습니다.
app/src/main/java/com/sampoom/android/feature/outbound/di/OutboundModules.kt (2)
15-20: LGTM!출고 리포지토리 바인딩이 올바르게 구현되었습니다. Hilt의
@Binds패턴을 적절히 사용했습니다.
22-27: LGTM!출고 API 제공이 올바르게 구현되었습니다. Retrofit API 인스턴스를 적절히 제공합니다.
app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt (4)
16-18: 하드코딩된 agency ID를 확인하세요.모든 엔드포인트에서
agency/1로 agency ID가 하드코딩되어 있습니다. 현재 단일 대리점만 지원하는 것이 의도된 동작인지, 향후 여러 대리점을 지원할 계획이 있는지 확인해주세요. 다중 대리점 지원이 필요하다면 agency ID를 파라미터로 받도록 리팩토링을 고려해야 합니다.
20-22: LGTM!장바구니 추가 엔드포인트가 올바르게 정의되었습니다.
24-26: LGTM!장바구니 항목 삭제 엔드포인트가 올바르게 정의되었습니다.
28-33: LGTM!장바구니 수량 변경 엔드포인트가 올바르게 정의되었습니다.
app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt (1)
25-26: 라우팅 전환 및 화면 바인딩 LGTMROUTE_OUTBOUND 도입과 OutboundListScreen/CartListScreen 연계가 일관됩니다. 내비게이션 동작 측면에서 문제 없어 보입니다.
Also applies to: 35-37, 135-137
app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt (5)
11-13: 의존성 주입이 올바르게 구현되었습니다.생성자에서
@Inject애노테이션을 사용하여 의존성 주입이 적절하게 설정되었습니다.
20-25: 에러 처리가 적절히 구현되었습니다.
runCatching과dto.success체크를 통한 에러 처리 패턴이 올바르게 적용되었습니다.
27-35: 에러 처리가 적절히 구현되었습니다.일관된 에러 처리 패턴이 잘 적용되었습니다.
37-49: 에러 처리가 적절히 구현되었습니다.
deleteOutbound()와deleteAllOutbound()메서드 모두 일관된 에러 처리 패턴을 따르고 있습니다.
51-59: 에러 처리가 적절히 구현되었습니다.일관된 에러 처리 패턴이 잘 적용되었습니다.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt (1)
22-24: TAG 상수 오타 미수정클래스명은
PartDetailViewModel인데 TAG 값이"OutboundDetailViewModel"로 설정되어 있습니다. 로그 추적 시 혼란을 야기할 수 있습니다.다음과 같이 수정하세요:
private companion object { - private const val TAG = "OutboundDetailViewModel" + private const val TAG = "PartDetailViewModel" }
🧹 Nitpick comments (2)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt (1)
357-380: 주석 처리된 코드 정리 고려OutlinedTextField 관련 코드가 대량으로 주석 처리되어 있습니다. 향후 사용 계획이 없다면 제거하여 코드 가독성을 높이는 것을 권장합니다. 재사용 가능성이 있다면 현재 상태로 유지해도 무방합니다.
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (1)
82-82: 프로덕션 로그 제거 권장전체 상태를 로깅하는 Log.d는 디버깅에는 유용하지만, 프로덕션 빌드에서는 성능과 보안을 위해 제거하거나 디버그 플래그 뒤에 두는 것을 권장합니다. (이 코멘트는 lines 105, 127, 170, 192에도 동일하게 적용됩니다)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt(2 hunks)app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt(2 hunks)app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt(1 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt(3 hunks)app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt
- app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt
- app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt
- app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt
🧰 Additional context used
🧬 Code graph analysis (3)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (4)
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (4)
updateQuantity(109-129)updateLocalQuantity(131-150)removeFromLocalList(196-215)removeAllFromLocalList(217-221)app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt (2)
deleteCart(25-26)deleteAllCart(36-37)app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt (2)
deleteCart(30-35)deleteAllCart(37-42)app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt (2)
deleteCart(8-8)deleteAllCart(9-9)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt (5)
app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt (3)
textColor(256-257)backgroundCardColor(253-254)textSecondaryColor(259-260)app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt (1)
ErrorContent(18-37)app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt (1)
EmptyContent(9-20)app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
CommonButton(49-176)app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (1)
onEvent(43-54)
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (4)
app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (4)
updateQuantity(107-127)updateLocalQuantity(129-148)removeFromLocalList(194-213)removeAllFromLocalList(215-219)app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt (2)
deleteOutbound(29-30)deleteAllOutbound(40-41)app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt (2)
deleteOutbound(37-42)deleteAllOutbound(44-49)app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt (2)
deleteOutbound(9-9)deleteAllOutbound(10-10)
🔇 Additional comments (20)
app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt (2)
24-26: 로깅 일관성 개선을 위한 TAG 상수 도입로깅 태그를 상수로 추출하여 유지보수성과 일관성을 높였습니다. 다른 ViewModel들과 동일한 패턴을 따르고 있어 좋습니다.
155-155: TAG 상수 사용으로 로깅 표준화하드코딩된 문자열 대신 TAG 상수를 사용하여 로깅이 표준화되었습니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt (1)
24-26: 로깅 일관성 개선을 위한 TAG 상수 도입로깅 태그를 상수로 추출하여 유지보수성과 일관성을 높였습니다.
app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt (2)
24-26: 로깅 일관성 개선을 위한 TAG 상수 도입로깅 태그를 상수로 추출하여 유지보수성과 일관성을 높였습니다. 다른 ViewModel들과 동일한 패턴을 따르고 있어 좋습니다.
91-91: TAG 상수 사용으로 로깅 표준화하드코딩된 문자열 대신 TAG 상수를 사용하여 로깅이 표준화되었습니다.
app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt (2)
4-4: import 수정 완료!이전 리뷰에서 지적된
jakarta.inject.Inject문제가javax.inject.Inject로 올바르게 수정되었습니다. Hilt DI와 호환되는 올바른 import입니다.
6-10: LGTM!UseCase 구현이 깔끔하고 표준 패턴을 따릅니다. Repository로의 단순 위임 구조가 적절합니다.
app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt (4)
14-14: import 수정 완료!이전 리뷰에서 지적된
jakarta.inject.Inject문제가javax.inject.Inject로 올바르게 수정되어 Hilt DI가 정상 작동합니다.
53-56: 수량 하한 처리 수정 완료!이전 리뷰에서 지적된 수량이 0 이하로 내려가는 문제가
maxOf(1L, currentQuantity - 1)로 올바르게 수정되었습니다.
93-105: Result 처리 개선 완료!이전 리뷰에서 지적된
runCatching래핑 문제가 해결되었습니다. 이제 UseCase가 반환하는Result<Unit>를 직접 처리하여 성공/실패를 정확하게 구분합니다.
114-126: Result 처리 개선 완료!AddCartUseCase 호출도 동일하게
Result를 직접 처리하도록 개선되어 실패 케이스를 올바르게 감지합니다.app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt (3)
154-167: 삭제 실패 처리 수정 완료!이전 리뷰에서 지적된 문제가 해결되었습니다. 삭제 실패 시
isDeleting=false,deleteError를 올바르게 설정하여 UI 상태를 정확히 반영합니다.
176-189: 전체 비우기 실패 처리 수정 완료!deleteAllCart 실패 처리도 동일하게
isDeleting=false,deleteError를 올바르게 설정하도록 수정되었습니다.
84-105: TODO: 주문 생성 로직 구현 대기 중processOrder 함수가 의도적으로 미구현 상태로 주석 처리되어 있습니다. 구현 시 주석된 패턴을 참고하여
cartLoading상태를 올바르게 관리하고, 성공 시loadCartList()를 호출하여 목록을 갱신하도록 구현하세요.app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt (2)
206-212: 다이얼로그 상태 처리 수정 완료!이전 리뷰에서 지적된 취소 버튼의 상태 변경 오류가 수정되었습니다. 이제
showEmptyCartDialog = false로 올바른 다이얼로그 상태를 변경합니다.
50-239: LGTM!CartListScreen의 전체 구조가 잘 구성되어 있습니다:
- ViewModel 연동 및 상태 관리가 적절함
- 로딩/에러/빈 목록 상태 처리가 명확함
- 다이얼로그 흐름이 올바르게 구현됨
- UI 이벤트 처리가 일관성 있게 구현됨
app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt (4)
17-17: javax.inject.Inject 사용 확인 완료이전 리뷰에서 지적된 jakarta.inject.Inject 문제가 수정되어 Hilt와 호환되는 javax.inject.Inject를 올바르게 사용하고 있습니다.
109-150: 수량 업데이트 로직 확인 완료
updateQuantity와updateLocalQuantity함수는 상태 관리와 불변 업데이트 패턴을 올바르게 구현하고 있으며, CartListViewModel과 일관된 패턴을 따르고 있습니다.
152-194: 삭제 작업 상태 관리 수정 확인이전 리뷰에서 지적된 삭제 실패 시 잘못된 상태 필드 사용 문제(
isUpdating/updateError대신isDeleting/deleteError)가 올바르게 수정되었습니다.deleteOutbound와deleteAllOutbound모두 적절한 상태 필드를 사용하고 있습니다.
196-221: 로컬 목록 제거 로직 확인 완료
removeFromLocalList와removeAllFromLocalList함수는 CartListViewModel과 동일한 패턴을 따르고 있으며, 불변성을 유지하면서 올바르게 구현되어 있습니다. 빈 그룹과 카테고리를 정리하는 로직도 적절합니다.
📝 Summary
출고목록, 장바구니 구현
출고목록 추가 로직, 장바구니 추가 로직 구현
출고처리 구현
🙏 Question & PR point
📬 Reference
Summary by CodeRabbit
새로운 기능
UI 개선