-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature/#154] 제보 상세조회 화면 구현 #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Walkthrough제보 상세조회 화면을 위한 전체 기능을 구현합니다. 도메인, 데이터, 표현 계층에 걸쳐 API 엔드포인트, 저장소, 뷰모델, UI 컴포넌트 및 네비게이션을 추가하여 보고서 상세 정보 조회 기능을 완성합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as ReportDetailScreen
participant ViewModel as ReportDetailViewModel
participant UseCase as GetReportUseCase
participant Repository as ReportRepository
participant DataSource as ReportDataSource
participant Service as ReportService
User->>UI: reportId로 화면 진입
UI->>ViewModel: compose 시 state 수집
ViewModel->>UseCase: invoke(reportId)
UseCase->>Repository: getReport(reportId)
Repository->>DataSource: getReport(reportId)
DataSource->>Service: getReport(reportId)
Service-->>DataSource: BaseResponse<ReportDetailDto>
DataSource-->>Repository: Result<ReportDetailDto>
Repository-->>UseCase: Result<ReportDetail>
UseCase-->>ViewModel: Result<ReportDetail>
ViewModel->>ViewModel: reduce(상태 업데이트)
ViewModel-->>UI: 업데이트된 ReportDetailState
UI->>UI: 리포트 정보 렌더링
UI-->>User: 제보 상세 화면 표시
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this 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
🧹 Nitpick comments (6)
data/src/main/java/com/threegap/bitnagil/data/address/model/response/Coord2AddressResponse.kt (1)
21-26:roadAddressnullable 변경은 역직렬화 에러 관점에서 적절해 보입니다.
Document.roadAddress를RoadAddress?로 바꿔서, 응답에"road_address": null이 오는 케이스에서도 역직렬화 예외 없이 처리될 것으로 보입니다. 현재toAddress()는 지번 주소(address.addressName)만 사용하고 있어 이번 변경과 직접적인 영향은 없지만, 도로명 주소를 우선 사용하고 싶다면 아래처럼 선택적으로 활용하는 것도 한 번 고려해 볼 수 있습니다 (선택 사항입니다):-fun Coord2AddressResponse.toAddress(): String? { - return this.documents - .firstOrNull() - ?.address - ?.addressName -} +fun Coord2AddressResponse.toAddress(): String? { + val first = documents.firstOrNull() ?: return null + return first.roadAddress?.addressName ?: first.address.addressName +}마지막으로, 실제 역지오코딩 API 응답 샘플(특히
road_address가 null 인 케이스)에 대해 역직렬화가 정상 동작하는지만 한 번만 테스트/QA 로 확인 부탁드립니다.Also applies to: 70-75
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/util/LocalDateUtils.kt (1)
7-10: DateTimeFormatter 재사용을 고려해보세요.현재 함수 호출마다 새로운
DateTimeFormatter인스턴스가 생성됩니다. 성능 개선을 위해 최상위 상수로 추출하는 것을 권장합니다.다음과 같이 리팩토링할 수 있습니다:
+private val REPORT_DETAIL_DATE_FORMATTER = DateTimeFormatter.ofPattern("yy.MM.dd (E)", Locale.KOREAN) + fun LocalDate.toPresentationFormatInReportDetail(): String { - val formatter = DateTimeFormatter.ofPattern("yy.MM.dd (E)", Locale.KOREAN) - return this.format(formatter) + return this.format(REPORT_DETAIL_DATE_FORMATTER) }presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/atom/ReportProcessBadge.kt (1)
33-46: ReportProcess 색상 매핑을else대신 명시적으로 처리하면 확장 시 더 안전합니다.현재
when (this)에서Reported,Progress만 명시하고 나머지는else로 처리하고 있어서, 추후ReportProcess에 새로운 상태가 추가되더라도 자동으로coolGray계열 색상으로 떨어져 버립니다. 상태별 뱃지 컬러가 기획에 중요한 요소라면,Complete까지 명시적으로 분기하고else는 제거하는 편이 나중에 상태가 늘어날 때 실수를 줄일 수 있습니다.@Composable private fun ReportProcess.getProcessBadgeBackgroundColor(): Color = when (this) { ReportProcess.Reported -> BitnagilTheme.colors.green10 ReportProcess.Progress -> BitnagilTheme.colors.skyBlue10 ReportProcess.Complete -> BitnagilTheme.colors.coolGray95 }텍스트 컬러 쪽도 동일하게 정리해 두면 좋을 것 같습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/ReportCategory.kt (1)
2-28: 도메인 enum alias를 파라미터 타입에도 사용하면 가독성이 좋아집니다.
DomainReportCategory로 alias import를 해두셨는데,fromDomain의 파라미터 타입은 FQCN을 그대로 쓰고 있어서 약간 혼재되어 보입니다. 아래처럼 alias를 타입에도 통일하면 코드 읽기가 더 수월할 것 같습니다.companion object { fun fromDomain(domainReportCategory: DomainReportCategory): ReportCategory = when (domainReportCategory) { DomainReportCategory.TRANSPORTATION -> TrafficFacilities DomainReportCategory.LIGHTING -> LightingFacilities DomainReportCategory.WATERFACILITY -> WaterFacilities DomainReportCategory.AMENITY -> Amenities } }동작은 동일하지만 스타일 측면에서 한 번 고려해 보셔도 좋겠습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/ReportDetailScreen.kt (2)
63-67: 상단 타이틀 문구가 상세 화면 컨텍스트와 다소 어긋나 보입니다.이 화면은 제보 작성이 아니라 상세 조회 화면인데, TopBar 제목이
"제보하기"라서 사용자가 제보 작성 플로우로 오인할 수도 있을 것 같습니다. 기획 의도에 따라"제보 상세","제보 내역"등 보다 명확한 문구로 바꾸는 것을 한 번 검토해 보시면 좋겠습니다.
88-102: 이미지 Row의 스크롤/간격 및 접근성 개선을 고려해 보시면 좋겠습니다.
- 현재
Row+forEach조합이라 이미지가 여러 장일 때 가로 폭을 넘어가면 뒤쪽 이미지가 잘릴 수 있지만 스크롤은 불가능합니다.horizontalScroll(rememberScrollState())를 Row에 추가하거나,LazyRow로 교체하면 자연스럽게 가로 스크롤이 가능해집니다.- 이미지 사이 간격이 없어 74dp 썸네일이 바로 붙어 보일 수 있습니다.
horizontalArrangement = Arrangement.spacedBy(8.dp)정도를 Row에 주면 더 읽기 쉬운 레이아웃이 될 것 같습니다.contentDescription = null이라 스크린리더에서 이 이미지들이 완전히 무시됩니다. 제보 내용과 직접 관련된 정보라면"제보 이미지 1","제보 이미지 2"등 간단한 설명이라도 넣어 두는 편이 접근성 측면에서 안전합니다.기능적으로는 문제 없지만, UX/a11y 측면에서 위 포인트들을 한 번 검토해 보시면 좋겠습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
app/src/main/java/com/threegap/bitnagil/MainNavHost.kt(2 hunks)app/src/main/java/com/threegap/bitnagil/Route.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/address/model/response/Coord2AddressResponse.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/report/datasource/ReportDataSource.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/report/datasourceImpl/ReportDataSourceImpl.kt(2 hunks)data/src/main/java/com/threegap/bitnagil/data/report/model/response/ReportDetailDto.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/report/repositoryImpl/ReportRepositoryImpl.kt(2 hunks)data/src/main/java/com/threegap/bitnagil/data/report/service/ReportService.kt(2 hunks)domain/src/main/java/com/threegap/bitnagil/domain/report/model/ReportDetail.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/report/repository/ReportRepository.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/report/usecase/GetReportUseCase.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/ReportDetailScreen.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/ReportDetailViewModel.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/atom/ReportProcessBadge.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/block/ReportDetailLabeledContent.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/ReportCategory.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/ReportProcess.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/mvi/ReportDetailSideEffect.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/mvi/ReportDetailState.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/navarg/ReportDetailScreenArg.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/util/LocalDateUtils.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/reporthistory/component/block/ReportHistoryItem.kt(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/atom/ReportProcessBadge.kt (1)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/Theme.kt (1)
BitnagilTheme(26-41)
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/ReportDetailScreen.kt (4)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilTopBar.kt (1)
BitnagilTopBar(22-63)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/atom/ReportProcessBadge.kt (1)
ReportProcessBadge(17-30)presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/block/ReportDetailLabeledContent.kt (1)
ReportDetailLabeledContent(16-42)core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/Theme.kt (1)
BitnagilTheme(26-41)
data/src/main/java/com/threegap/bitnagil/data/report/datasourceImpl/ReportDataSourceImpl.kt (1)
data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt (1)
safeApiCall(10-25)
app/src/main/java/com/threegap/bitnagil/MainNavHost.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/ReportDetailScreen.kt (1)
ReportDetailScreenContainer(36-47)
⏰ 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
🔇 Additional comments (15)
presentation/src/main/java/com/threegap/bitnagil/presentation/reporthistory/component/block/ReportHistoryItem.kt (1)
20-20: LGTM! 이미지 표시 개선이 적절합니다.
ContentScale.Crop추가로 제보 목록의 썸네일 이미지가 컨테이너에 맞게 크롭되어 더 일관된 UI를 제공합니다.Also applies to: 87-87
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/mvi/ReportDetailSideEffect.kt (1)
1-3: LGTM! MVI 패턴 구조가 적절합니다.빈 인터페이스는 추후 sealed interface로 확장할 수 있는 side effect의 마커 타입으로 적절합니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/ReportProcess.kt (1)
5-21: LGTM! 도메인-프레젠테이션 매핑이 깔끔합니다.enum 정의와
fromDomain매퍼가 모든ReportStatus케이스를 처리하며, UI 표시용 한글 타이틀도 적절합니다.app/src/main/java/com/threegap/bitnagil/Route.kt (1)
58-59: LGTM! 라우트 정의가 기존 패턴과 일관됩니다.새로운
ReportDetail라우트가 기존 라우트들과 동일한 패턴으로 정의되었으며, 타입 안전한 네비게이션을 위한 Serializable 어노테이션도 적절합니다.data/src/main/java/com/threegap/bitnagil/data/report/service/ReportService.kt (1)
21-24: LGTM! API 엔드포인트 정의가 표준 패턴을 따릅니다.Retrofit을 사용한 GET 엔드포인트 정의가 RESTful 규칙과 기존 코드 스타일에 부합합니다.
reportId유효성 검증은 백엔드에서 처리될 것으로 가정합니다.data/src/main/java/com/threegap/bitnagil/data/report/datasource/ReportDataSource.kt (1)
10-10: LGTM! 인터페이스 확장이 기존 패턴과 일관됩니다.새로운
getReport메서드가 기존 메서드들과 동일한Result래핑 패턴을 따르며, 시그니처도 명확합니다.data/src/main/java/com/threegap/bitnagil/data/report/repositoryImpl/ReportRepositoryImpl.kt (1)
25-27: LGTM! 리포지토리 구현이 클린 아키텍처 패턴을 준수합니다.데이터소스 호출과 도메인 매핑이 명확하게 분리되어 있으며,
Result.map을 활용한 에러 핸들링도 적절합니다.domain/src/main/java/com/threegap/bitnagil/domain/report/usecase/GetReportUseCase.kt (1)
7-13: 깔끔한 유스케이스 구현입니다.단일 책임 원칙을 잘 따르고 있으며, 리포지토리에 대한 명확한 위임 구조를 가지고 있습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/navarg/ReportDetailScreenArg.kt (1)
5-8: 네비게이션 인자가 올바르게 정의되었습니다.
@Serializable어노테이션을 사용하여 타입 세이프한 네비게이션을 지원하고 있습니다.domain/src/main/java/com/threegap/bitnagil/domain/report/repository/ReportRepository.kt (1)
4-4: 리포지토리 인터페이스가 일관성 있게 확장되었습니다.기존 메서드들과 동일한 패턴을 따르고 있으며,
Result타입을 사용하여 에러 핸들링을 지원합니다.Also applies to: 11-11
data/src/main/java/com/threegap/bitnagil/data/report/datasourceImpl/ReportDataSourceImpl.kt (1)
22-24: 데이터 소스 구현이 올바릅니다.
safeApiCall을 통해 적절한 에러 핸들링이 이루어지고 있으며, 기존 메서드들과 일관된 패턴을 따릅니다.presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/component/block/ReportDetailLabeledContent.kt (1)
16-42: 재사용 가능한 UI 컴포넌트가 잘 구현되었습니다.디자인 시스템을 일관성 있게 적용하고 있으며, 명확한 시각적 계층 구조를 제공합니다.
domain/src/main/java/com/threegap/bitnagil/domain/report/model/ReportDetail.kt (1)
5-14: 도메인 모델이 명확하게 정의되었습니다.불변 데이터 클래스로 구현되어 있으며, 적절한 타입을 사용하고 있습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/model/mvi/ReportDetailState.kt (1)
7-25: ReportDetailState 설계가 화면 요구사항과 잘 맞습니다.프로세스/제목/내용/카테고리/이미지/위치/날짜까지 상세 화면에서 필요한 정보가 과하게 섞이지 않고 한 곳에 잘 모여 있고,
Init기본값도 Preview 및 초기 상태로 재사용하기에 적절해 보입니다. ViewModel 쪽 로직과 연동만 잘 되어 있다면 이쪽은 그대로 사용해도 무방해 보입니다.app/src/main/java/com/threegap/bitnagil/MainNavHost.kt (1)
325-347: ReportDetail 네비게이션/뷰모델 연결 패턴이 기존 구조와 잘 일치합니다.
ReportHistoryScreenContainer에서navigateToReportDetail(reportId)를 받아Route.ReportDetail(reportId = reportId)로 이동하는 구조가 Home → WriteRoutine 등 기존 화면들과 동일한 패턴이라 이해하기 쉽습니다.composable<Route.ReportDetail>내부에서toRoute<Route.ReportDetail>()로 타입 안전하게 인자를 복원하고,ReportDetailScreenArg→ReportDetailViewModel.Factory.create(...)→ReportDetailScreenContainer로 이어지는 흐름도 OnBoarding/WriteRoutine과 동일해 일관성이 좋습니다.- 뒤로 가기 시
previousBackStackEntry여부를 확인한 뒤popBackStack()하는 패턴도 다른 화면과 동일합니다.현재 구성은 그대로 사용해도 괜찮아 보입니다.
data/src/main/java/com/threegap/bitnagil/data/report/model/response/ReportDetailDto.kt
Show resolved
Hide resolved
data/src/main/java/com/threegap/bitnagil/data/report/model/response/ReportDetailDto.kt
Show resolved
Hide resolved
...ation/src/main/java/com/threegap/bitnagil/presentation/reportdetail/ReportDetailViewModel.kt
Show resolved
Hide resolved
wjdrjs00
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다..! (바로 어푸 찍었슴다! 리뷰확인하고 머지해주세요~)
히스토리랑 상세조회랑 중복된 코드가 있긴한데, 우선 서비스적 문제라기 보단 아키텍처적 이슈라 생각되어 추후 수정해봐도 좋을거 같숩니다!
- 도로명 주소의 경우 제 활동바운더리에서는 항상 성공만해서 확인을 못했는데,, 수정 감사합니다요~!
[ PR Content ]
제보 상세조회 화면을 구현합니다.
Related issue
Screenshot 📸
KakaoTalk_Video_2025-11-23-13-24-12.mp4
Work Description
To Reviewers 📢
ETC
Summary by CodeRabbit
릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings.