Skip to content

분석 리포트 화면 구현 및 발표 분석 리포트 플로우 연동#139

Merged
moondev03 merged 30 commits into
developfrom
feat/#134-분석-리포트-화면-구현
May 26, 2026

Hidden character warning

The head ref may contain hidden characters: "feat/#134-\ubd84\uc11d-\ub9ac\ud3ec\ud2b8-\ud654\uba74-\uad6c\ud604"
Merged

분석 리포트 화면 구현 및 발표 분석 리포트 플로우 연동#139
moondev03 merged 30 commits into
developfrom
feat/#134-분석-리포트-화면-구현

Conversation

@moondev03
Copy link
Copy Markdown
Member

@moondev03 moondev03 commented May 25, 2026

📌 작업 내용

이번 PR에서는 발표 분석 리포트 기능을 end-to-end로 연결했습니다.

1. 분석 리포트 화면 구현

  • feature/report/impl에 분석 리포트 화면을 구현했습니다.
  • 리포트 헤더, 요약 피드백, 정확도, 성장 그래프, 대본 분석, 예상 질문, 셀프 피드백, 빈 상태 UI를 구성했습니다.
  • 삭제/재녹음/대본 재작성 다이얼로그와 관련 액션을 추가했습니다.
  • report 모듈 문자열 리소스를 정리하고 하드코딩 문자열을 strings.xml 기반으로 치환했습니다.

2. 리포트 데이터 플로우 및 도메인/데이터 계층 확장

  • 발표 분석 요청/조회/삭제/재분석을 위한 presentation 중심 모델과 유즈케이스를 추가했습니다.
  • PresentationRepository, PresentationRemoteDataSource, PresentationService와 관련 response/model/mapper를 추가해
    발표 목록 조회, 리포트 상세 조회, 스크립트/단어 상세 조회, 분석 삭제 흐름을 분리했습니다.
  • 기존 practice 중심 일부 구조를 정리하고 presentation 도메인으로 책임을 이동했습니다.
  • 발표 분석 요약 정보의 일부 필드를 null 허용으로 조정해 실제 응답 구조에 맞췄습니다.

3. 분석/히스토리/내비게이션 연동

  • 분석 완료 후 리포트 진입 경로를 개선하고, ID 기반으로 리포트 상세를 조회하도록 구조를 변경했습니다.
  • 히스토리 화면에서 발표 목록을 조회하고, 완료/진행 예정 발표에 따라 리포트 진입이 가능하도록 연동했습니다.
  • 히스토리 화면에 분석하기 진입 액션을 추가했습니다.
  • Navigator 및 entry builder를 조정해 report/analysis 이동 흐름을 정리했습니다.

4. 예외 처리 및 사용자 알림

  • 분석 리포트 최초 조회 실패 시 snackbar 노출 후 이전 화면으로 복귀하도록 처리했습니다.
  • 분석 리포트 삭제 실패 시 현재 화면을 유지한 채 snackbar로 실패 메시지를 보여주도록 처리했습니다.
  • 이를 위해 AnalysisReportUiEffect.ShowMessage, AnalysisReportUiMessage와 관련 문자열 리소스를 추가했습니다.

5. 공통 UI/디자인 시스템 보완

  • report 화면 구현에 필요한 아이콘/버튼/리스트 관련 보완을 반영했습니다.
  • PrezelIconButton, PrezelList, 아이콘 리소스 등을 일부 수정해 리포트 UI와 연동했습니다.

🧩 관련 이슈


📸 스크린샷

Screen_recording_20260526_040203.mp4

📢 논의하고 싶은 내용

  • 다시 녹음하기, 다시 대본쓰기는 다음 브랜치에서 구현하도록 하겠습니다.
  • 다시 녹음하기의 경우 노출되는 다이얼로그 문구 재확인이 필요합니다.
  • #115에서 분석 관련 API가 Practice로 되어있어서 Presentation으로 옮겼습니다.

Summary by CodeRabbit

  • New Features

    • 분석 리포트 화면 추가(상세 메트릭·성장 그래프·스크립트/단어 분석·예상 질문·셀프피드백)
    • 예정/지난 발표 목록 및 상세 조회 기능 추가
    • 발표 분석 생성/재실행 및 분석 삭제 기능 추가
    • 리포트에서 재녹음·대본 재작성·피드백 작성으로 이동 가능
  • Refactor

    • 발표 관련 도메인/데이터 모델 및 매핑 정비
    • 네트워크·리포지토리·유스케이스 구조 분리·정리
    • UI 상태/네비게이션 흐름 개선

Review Change Stack

moondev03 added 19 commits May 25, 2026 17:24
# Conflicts:
#	Prezel/core/data/src/main/java/com/team/prezel/core/data/error/AppErrorExt.kt
* **refactor: `PresentationMapper` 추가 및 데이터 변환 로직 이동**
    * `PresentationRepositoryImpl` 내부에 비대하게 존재하던 도메인 모델과 네트워크 DTO 간의 변환 로직을 별도의 `PresentationMapper.kt` 파일로 추출했습니다.
    * `PresentationAnalysisSummary`, `PresentationScriptDetail`, `PresentationWordDetail` 등 주요 데이터 구조에 대한 `toDomain` 확장 함수를 정의했습니다.
    * `Category`, `Purpose`, `Style`, `Audience` 등 도메인 모델과 서버 간의 타입 매핑 로직(enum to string)을 통합 관리하도록 개선했습니다.
    * `kotlinx-datetime`을 사용하여 날짜 문자열을 `Instant`로 파싱하는 로직(`toAnalysisInstant`)에 대한 예외 처리를 강화했습니다.

* **refactor: `PresentationRepositoryImpl` 구조 개선**
    * 데이터 매핑 로직이 분리됨에 따라 Repository 내의 불필요한 private 메서드들을 제거하고 코드를 간결화했습니다.
    * 네트워크 요청 시 `PresentationAnalysisRequest`를 `PresentationAnalysisRequestParts`로 변환할 때 새로운 매퍼를 사용하도록 수정했습니다.
* **refactor: 타이틀 텍스트의 `maxLines` 속성 제거**
    * `PrezelList` 내 타이틀을 표시하는 `Text` 컴포넌트에서 `maxLines = 1` 제약을 제거하여, 긴 제목이 생략되지 않고 여러 줄로 표시될 수 있도록 수정했습니다.
* **refactor: `Navigator.navigate` 메서드 시그니처 및 로직 수정**
    * 특정 목적지로 이동 시 현재 하위 스택을 비울 수 있도록 `clearStack` 매개변수를 추가했습니다.
    * 목적지 이동 처리를 담당하는 `goToKey` 호출 시 `clearStack` 옵션을 전달하도록 변경했습니다.

* **refactor: `goToKey` 내 스택 관리 정책 업데이트**
    * `clearStack` 옵션이 활성화된 경우, 현재 하위 스택에서 루트 요소를 제외한 모든 경로를 제거한 뒤 새로운 목적지를 추가하도록 로직을 개선했습니다.
    * 하위 스택 내 동일 키는 1개만 유지하는 기존 정책을 유지하면서, 필요에 따라 스택을 초기화할 수 있는 유연성을 확보했습니다.
* **feat: `HttpTimeout` 설정 추가 및 적용**
    * `HttpClientFactory` 내에 `installHttpTimeout` 함수를 정의하고 소켓 타임아웃(`socketTimeoutMillis`)을 30초로 설정했습니다.
    * 분석 결과 대기 시간 등으로 인한 응답 지연에 대응하기 위해 기본 HTTP 클라이언트 설정에 이를 추가했습니다.

* **refactor: 로깅 시 인증 헤더 마스킹 로직 개선**
    * `Logging` 플러그인 설정에서 `Authorization` 헤더를 마스킹하는 `sanitizeHeader` 처리가 디버그 모드가 아닐 때(`!BuildConfig.DEBUG`)만 동작하도록 변경했습니다.
    * 이를 통해 디버그 환경에서 네트워크 로그를 통한 인증 토큰 확인이 가능하도록 개선했습니다.
* **refactor: 도메인 Enum 클래스 구조 표준화 및 기능 추가**
    * `Style`, `Category`, `Purpose`, `Audience`, `PracticeRecordingOverallEvaluation` 등 주요 Enum 클래스에 `value` 프로퍼티와 문자열 기반의 `from()` 팩토리 메서드를 추가했습니다.
    * 기존의 `PracticeRecordingSpeed`를 삭제하고, 한국어 값을 포함한 공통 Enum인 `RecordingSpeed`를 새롭게 정의하여 통합했습니다.

* **refactor: 분석 결과 데이터 모델 필드 타입 조정**
    * `PresentationAnalysisSummary`의 `analyzedAt` 필드 타입을 `Instant`에서 `String`으로 변경했습니다.
    * `speedEvaluation` 및 `speed` 필드 타입을 단순 `String` 또는 개별 Enum에서 공통 Enum인 `RecordingSpeed`로 변경하여 타입 안정성을 높였습니다.

* **cleanup: 불필요한 도메인 모델 삭제**
    * 더 이상 사용되지 않는 `PresentationRecordingAnalysisResult` 클래스를 제거하여 코드를 정리했습니다.
* **refactor: 발표 분석 요청 파라미터 구조 변경 및 UseCase 고도화**
    * `AnalyzePresentationUseCase` 및 `PresentationRepository`에서 `PresentationAnalysisRequest` 객체 대신 개별 필드(name, date, category 등)를 직접 전달받도록 변경했습니다.
    * `AnalyzePresentationRecordingUseCase`를 삭제하고 관련 기능을 `AnalyzePresentationUseCase`로 통합했습니다.

* **refactor: Practice 모듈 내 발표 분석 로직 제거 및 Presentation 모듈로 일원화**
    * `PracticeRemoteDataSource`, `PracticeRepository` 및 관련 구현체에서 발표 분석 관련 메서드(`analyzePresentationRecording`)를 삭제했습니다.
    * `PracticeMapper`에서 발표 분석 응답 변환 로직을 제거하고, `RecordingSpeed` 및 `PracticeRecordingOverallEvaluation`의 enum factory 메서드를 사용하도록 개선했습니다.

* **refactor: PresentationRemoteDataSource 파일 업로드 및 매핑 로직 개선**
    * `analyzePresentation` 호출 시 `readBytes()` 대신 `ChannelProvider`와 `toByteReadChannel()`을 사용한 스트리밍 방식으로 멀티파트 데이터를 처리하도록 개선하여 메모리 효율성을 높였습니다.
    * 대본 파일 업로드를 위한 `scriptFile` 파트 처리 로직(`appendTextPart`)을 추가했습니다.
    * `PresentationMapper` 내 수동 매핑 로직을 도메인 모델의 `from()` 메서드 호출 방식으로 전환하여 응집도를 높였습니다.

* **cleanup: 불필요한 클래스 및 테스트 코드 제거**
    * 더 이상 사용되지 않는 `PresentationAnalysisRequest` 데이터 모델을 제거했습니다.
    * 구조 변경에 따라 유효하지 않게 된 `PresentationRepositoryImplTest`를 삭제했습니다.
    * `AppErrorExt` 내 불필요한 들여쓰기를 정리했습니다.
* **refactor: `ReportAnalysisPayload` 데이터 구조 평탄화**
    * `ReportPresentationInfoPayload` 클래스를 제거하고 내부 필드(`title`, `category`, `purpose`, `style`, `audience`, `analyzedAt`)를 `ReportAnalysisPayload`의 최상위 필드로 이동했습니다.
    * `speedEval` 필드명을 `speedEvaluation`으로 변경하고 타입을 Enum에서 `String`으로 변경했습니다.

* **refactor: 중복된 페이로드 Enum 및 클래스 정리**
    * 도메인 모델과 유사하게 정의되었던 `ReportCategoryPayload`, `ReportPurposePayload`, `ReportStylePayload` 등 개별 Enum 클래스들을 삭제하고 `String` 기반으로 연동하도록 수정했습니다.
    * `ReportGrowthPayload`를 `PresentationGrowthPointPayload`로, `ReportExpectedQuestionPayload`를 `ExpectedQuestionPayload`로 이름을 변경하여 의미를 명확히 했습니다.

* **refactor: 도메인 모델 변환 로직 최적화**
    * 외부 함수였던 `toReportAnalysisPayload`를 `ReportAnalysisPayload` 컴패니언 객체의 `toPayload` 확장 함수로 이동했습니다.
    * 복잡한 `when` 분기 처리 대신 도메인 모델의 `value` 프로퍼티를 직접 참조하도록 매핑 로직을 간소화했습니다.
* **refactor: 분석 프로세스 종료 후 리포트 모듈 내비게이션 연결**
    * 분석 완료 시 내부의 `AnalysisReportScreen`을 보여주는 대신, `ReportNavKey.Analysis`를 통해 리포트 기능 모듈로 이동하도록 로직을 변경했습니다.
    * `AnalysisFlowViewModel`에서 분석 성공 시 `NavigateToReport` 이벤트를 발생시키고, 이를 처리하기 위해 `feature:report:api` 의존성을 추가했습니다.
    * `AnalyzePresentationRecordingUseCase`를 최신 도메인 요구사항에 맞춰 `AnalyzePresentationUseCase`로 교체했습니다.

* **refactor: 리포트 및 연습 분석 UI 모델과 매핑 로직 개선**
    * `ReportAnalysisPayload`를 UI 상태로 변환하는 매핑 로직을 core 도메인 모델의 `from()` 메서드를 활용하도록 단순화했습니다.
    * `PresentationInfoUiModel`의 시간 관련 타입을 `Instant`에서 `String`으로, `formattedDuration`에서 `durationSeconds(Int)`로 변경하여 데이터 일관성을 확보했습니다.
    * `ReportHeaderSection` 내부에 기간(Duration) 표시를 위한 `toDurationString()` 확장 함수를 추가하고 날짜 포맷팅 로직을 내재화했습니다.

* **refactor: 공통 도메인 모델 통합 및 불필요한 코드 제거**
    * 각 모듈(`practice`, `report`)에서 개별적으로 정의해 사용하던 속도 관련 enum을 core 모듈의 `RecordingSpeed`로 통합했습니다.
    * `Category`, `Purpose`, `Style`, `Audience` 등의 모델 상수 명칭 변경(예: `PERSUASION` -> `OFFER`, `PROFESSIONAL` -> `FORMAL`)에 맞춰 관련 리소스 매핑 로직을 업데이트했습니다.
    * 더 이상 사용되지 않는 `AnalysisReportScreen.kt` 및 `ReportDetailFormatters.kt` 파일을 삭제했습니다.

* **build: 모듈 간 의존성 조정**
    * `app` 모듈 및 `feature:analysis:impl` 모듈에 리포트 관련 의존성을 추가했습니다.
* **refactor: 화면 간 데이터 전달 방식을 객체 전달에서 ID 기반 조회로 변경**
    * `ReportNavKey.Analysis`에서 거대한 데이터 객체인 `ReportAnalysisPayload`를 전달하던 방식을 `presentationId (Long)`를 전달하는 방식으로 수정했습니다.
    * 이에 따라 더 이상 사용되지 않는 `ReportAnalysisPayload` 클래스와 관련 매퍼 로직을 삭제했습니다.
    * `AnalyzePresentationUseCase` 및 `PresentationRepository`의 분석 결과 반환 타입을 `PresentationAnalysisSummary`에서 `Long` (발표 ID)으로 변경했습니다.

* **feat: 분석 상세 데이터 조회를 위한 UseCase 및 네트워크 로직 추가**
    * 발표 ID를 통해 상세 분석 정보를 가져오는 `FetchPresentationDetailUseCase`를 추가했습니다.
    * `PresentationRepository` 및 `PresentationRemoteDataSource`에 `getUpcomingPresentationDetail` 기능을 구현했습니다.
    * `PresentationService`에 `/recording/{presentationId}/upcoming` API 정의를 추가했습니다.

* **refactor: `AnalysisReportViewModel` 데이터 로드 로직 수정**
    * ViewModel 생성 시점에 `navKey`로부터 받은 페이로드를 바로 상태에 반영하던 방식에서, `presentationId`를 사용해 데이터를 비동기로 fetch 하도록 초기화 로직을 변경했습니다.
    * `AnalysisReportUiState.Loading` 상태를 추가하여 데이터 로딩 중 UI를 처리할 수 있도록 개선했습니다.

* **refactor: 리포트 UI 컴포넌트 구조화 및 재사용성 강화**
    * `AnalysisReportContent`를 삭제하고 공통 컴포넌트인 `ReportDetailScreen`으로 통합했습니다.
    * `ReportDetailScreen`에서 뒤로가기 버튼 처리 및 상단 액션 구성을 일원화했습니다.
    * `HistoryReportContent` 내의 중복된 TopAppBar 아이콘 설정 로직을 `ReportDetailScreen`의 공통 속성으로 이동했습니다.

* **build: 의존성 정리**
    * `feature:report:impl` 모듈에 UseCase 사용을 위한 `core:domain` 의존성을 추가했습니다.
    * `feature:report:api` 모듈에서 불필요해진 `core:model` 및 날짜 관련 의존성을 제거했습니다.
* **feat: 발표 목록(예정/지난) 및 상세 조회 기능 추가**
    * `PresentationService` 및 `RemoteDataSource`에 예정된/지난 발표 목록 및 상세 조회 API 연동을 위한 메서드를 추가했습니다.
    * `FetchUpcomingPresentationsUseCase`, `FetchPastPresentationsUseCase`를 추가하여 목록 조회 로직을 캡슐화했습니다.
    * `PresentationRepository` 인터페이스 및 구현체에 관련 조회 로직을 반영했습니다.

* **refactor: 프레젠테이션 도메인 및 데이터 모델 개선**
    * 기존 `Presentation` 모델을 삭제하고, 목록 조회 스펙에 맞춘 `PresentationInfo` 모델을 새롭게 정의했습니다.
    * `PresentationAnalysisSummary` 및 `PresentationSummaryResponse`에 셀프 피드백(`selfFeedback`, `reviewContent`) 필드를 추가했습니다.
    * 네트워크 응답 처리를 위한 `GetPresentationsResponse` DTO를 추가했습니다.

* **refactor: 매퍼 로직 업데이트 및 가시성 조정**
    * `PresentationMapper`에 `GetPresentationsResponse`를 `PresentationInfo`로 변환하는 로직을 추가했습니다.
    * 매퍼 내에서만 사용되는 일부 변환 함수들의 가시성을 `internal`에서 `private`으로 변경하여 캡슐화를 강화했습니다.
* **refactor: 리포트 탐색 키 및 진입 로직 단순화**
    * `ReportNavKey`를 `History`, `Analysis` sealed interface에서 `presentationId`와 `isPast` 플래그를 가진 단일 data class로 통합했습니다.
    * `AnalysisEntryBuilder`에서 리포트 이동 시 변경된 `ReportNavKey`를 사용하도록 수정했습니다.

* **refactor: 리포트 화면 UI 구조 통합 및 컴포넌트 재구성**
    * 기존에 분리되어 있던 `AnalysisReport`와 `HistoryReport` 관련 UI 로직을 `AnalysisReportScreen`으로 통합했습니다.
    * `ReportDetailLayout`을 `ReportScreenLayout`으로, `ReportDetailSections`를 `ReportBodyContent` 등으로 명칭을 변경하고 구조를 개선했습니다.
    * 리포트 컴포넌트들을 기능별(`body`, `common`) 패키지로 분리하고 `ReportSection`, `MetricResultCard` 등 공통 컴포넌트 가시성을 조정했습니다.
    * `ImprovementGraph` 관련 명칭을 `GrowthGraph`로 일괄 변경했습니다.

* **refactor: 리포트 ViewModel 및 도메인 로직 개선**
    * `HistoryReportViewModel`을 삭제하고 `AnalysisReportViewModel`에서 과거/현재 리포트를 모두 처리하도록 통합했습니다.
    * `FetchPresentationDetailUseCase`에 `isPast` 파라미터를 추가하여 과거 발표 데이터 조회 기능을 지원합니다.
    * `AnalysisReportUiState`에 `isPast`, `selfFeedback` 등을 추가하여 화면 상태 정의를 확장했습니다.

* **feat: 히스토리 화면 기능 고도화 및 네비게이션 연동**
    * `HistoryViewModel`에 `FetchUpcomingPresentationsUseCase`와 `FetchPastPresentationsUseCase`를 적용하여 실제 데이터를 fetch하도록 개선했습니다.
    * 히스토리 아이템 클릭 시 해당 리포트 화면으로 이동하는 `NavigateToReport` 효과를 추가했습니다.
    * `HistoryPresentationCard`의 카테고리 칩에 디자인 시스템 아이콘을 적용했습니다.

* **cleanup: 불필요한 코드 및 리소스 정리**
    * 더 이상 사용되지 않는 `HistoryReportViewModel`, `HistoryReportUiState`, `ReportDetailPreviewData` 등을 삭제했습니다.
    * `Presentation` 모델을 `PresentationInfo`로 대체하고 D-Day 계산 로직을 간소화했습니다.
* **feat: 분석 리포트 관련 다이얼로그(`ReportDialog`) 추가**
    * 리포트 삭제, 다시 녹음, 대본 다시 쓰기 시나리오를 지원하는 공통 다이얼로그 컴포넌트를 구현했습니다.
    * `AnalysisReportDialog` enum을 정의하여 각 다이얼로그 타입에 따른 타이틀, 설명, 버튼 스타일을 관리합니다.
    * `strings.xml`에 다이얼로그 구성에 필요한 리소스 문자열을 추가했습니다.

* **feat: 리포트 삭제 기능 및 ViewModel 로직 연동**
    * `DeletePresentationAnalysisUseCase`를 주입받아 실제 분석 리포트 삭제 기능을 구현했습니다.
    * 삭제 버튼 클릭 시 즉시 삭제 대신 확인 다이얼로그를 노출하도록 변경하고, 다이얼로그 승인 시 삭제 프로세스를 진행합니다.
    * `AnalysisReportUiIntent`에 다이얼로그 노출 및 제어를 위한 `DismissDialog`, `ClickDialogConform` 의도를 추가했습니다.

* **refactor: 화면 탐색 및 모듈 의존성 정리**
    * 리포트 삭제 또는 작업 완료 후 홈 화면으로 이동(`NavigateHome`)하던 로직을 이전 화면으로 돌아가는 `NavigateToBack`으로 변경했습니다.
    * `feature:report:impl` 모듈에서 더 이상 사용하지 않는 `feature:home:api` 의존성을 제거했습니다.
    * `AnalysisReportViewModel` 내 상태 업데이트 로직을 `updateContent` 확장 함수로 캡슐화하여 가독성을 개선했습니다.
* **feat: 히스토리 화면 내 분석 페이지 이동 로직 구현**
    * `HistoryScreen` 및 하위 컴포넌트(`HistoryContent`, `HistoryEmptyContent`)에 `navigateToAnalysis` 콜백을 추가하여 분석하기 버튼 클릭 시의 동작을 정의했습니다.
    * `HistoryEntryBuilder`에서 `AnalysisNavKey.Create`를 통해 분석 화면으로 이동하도록 내비게이션 로직을 연결했습니다.
    * `feature:history:impl` 모듈의 `build.gradle.kts`에 `feature:analysis:api` 의존성을 추가했습니다.

* **refactor: 분석 화면 네비게이션 동작 수정**
    * `AnalysisScreen`의 뒤로가기(`onBack`) 동작을 기존의 `replaceRoot(HomeNavKey)`에서 `goBack()`으로 변경하여 이전 화면으로 자연스럽게 복귀하도록 개선했습니다.
* **refactor: `PresentationAnalysisSummary` 및 `PresentationSummaryResponse` 필드 수정**
    * 발표 분석 결과의 `accuracyScore`(정확도 점수)와 `scriptMatchRate`(대본 일치율) 필드를 필수 값에서 선택 값(`Double?`)으로 변경했습니다.
    * 네트워크 응답 모델(`PresentationSummaryResponse`)에서 해당 필드가 누락되거나 없는 경우를 처리할 수 있도록 기본값 `null`을 추가했습니다.
* **feat: 분석 리포트 내 스크립트 및 녹음 관련 내비게이션 및 의존성 추가**
    * `AnalysisReportUiIntent`에 스크립트 다시 쓰기(`ClickReWriteScript`) 및 다시 녹음하기(`ClickReRecording`) 인텐트를 추가했습니다.
    * `AnalysisReportUiEffect`에 스크립트 및 녹음 분석 화면으로의 이동을 위한 `NavigateToAnalysisScript`, `NavigateToAnalysisRecording`을 추가했습니다.
    * `AnalysisReportViewModel`에서 해당 인텐트 발생 시 상태에 따라 다이얼로그를 표시하거나 화면 이동을 처리하는 로직을 구현했습니다.

* **refactor: 스크립트 분석 및 정확도 섹션의 데이터 처리 방식 개선**
    * `AnalysisReportUiState`의 `accuracyScore`와 `scriptMatchRate`를 nullable(`Double?`)로 변경하여 대본이 없는 상태를 표현할 수 있도록 개선했습니다.
    * 스크립트 작성 여부를 판단하는 `isScriptWritten` 프로퍼티를 추가하고, 이에 따라 `ScriptAnalysisSection`에서 분석 결과 또는 스크립트 입력 유도 UI(Empty State)를 분기 처리하도록 수정했습니다.

* **ui: 공통 컴포넌트 추출 및 디자인 시스템 적용**
    * 여러 섹션에서 중복 사용되던 빈 화면 처리 로직을 `EmptyStateCard` 공통 컴포넌트로 분리했습니다.
    * 하드코딩된 문자열들을 `strings.xml` 리소스로 대체하고, 툴팁 및 스피드 라벨 등에 다국어 대응을 적용했습니다.
    * `GrowthGraphSection` 및 `ScriptAnalysisSection`에 다시 녹음/다시 쓰기 버튼을 추가하고 클릭 이벤트를 연결했습니다.

* **fix: 데이터 모델 안정성 강화**
    * `GrowthGraphData`에서 `selectedItem` 접근 시 `getOrNull`을 사용하여 인덱스 범위 초과 에러를 방지하고, `init` 블록의 validation 메시지를 강화했습니다.
    * `Double?.toPercentLabel()` 확장 함수가 null 값을 처리할 수 있도록 수정했습니다.
* **feat: 분석 리포트 UI 메시지 처리 로직 추가**
    * 에러 상황(조회 실패, 삭제 실패)을 정의하는 `AnalysisReportUiMessage` enum을 추가했습니다.
    * 각 에러 상황에 대응하는 문자열 리소스를 추가하고, 이를 UI 메시지 모델과 연결하는 `resId` 확장 프로퍼티를 구현했습니다.

* **feat: `AnalysisReportUiEffect` 내 메시지 표시 액션 추가**
    * UI 레이어에 메시지 출력을 요청하는 `ShowMessage` 효과를 추가했습니다.
    * `AnalysisReportScreen`에서 해당 효과를 수집하여 `LocalSnackbarHostState` 및 `showPrezelSnackbar`를 통해 사용자에게 알림을 표시하도록 구현했습니다.

* **refactor: `AnalysisReportViewModel` 내 에러 핸들링 로직 개선**
    * `fetchAnalysisReport` 호출 실패 시 에러 메시지를 전송하고 이전 화면으로 자동 이동(`NavigateToBack`)하도록 로직을 추가했습니다.
    * `deleteReport` 호출 실패 시 사용자에게 실패 알림을 전송하는 예외 처리를 적용했습니다.
@moondev03 moondev03 self-assigned this May 25, 2026
@moondev03 moondev03 requested a review from HamBeomJoon as a code owner May 25, 2026 18:50
@moondev03 moondev03 added the ✨ feat 새로운 기능 추가 또는 기존 기능 확장 label May 25, 2026
@moondev03 moondev03 linked an issue May 25, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

📝 Walkthrough

Walkthrough

프레젠테이션 분석 도메인·네트워크·데이터 경로와 매퍼·리포지토리를 추가하고, 분석 리포트 UI·상태·뷰모델·네비게이션을 구현했습니다. 분석 플로우·히스토리·홈을 새 모델로 전환하고 디자인시스템·내비게이터·빌드/DI/타임아웃·에러코드를 보완했습니다.

Changes

Presentation 분석·리포트 통합 변경

Layer / File(s) Summary
도메인 계약 및 유스케이스
core/domain/...
PresentationRepository 인터페이스와 분석 관련 유스케이스(Analyze/ReAnalyze/FetchUpcoming/FetchPast/FetchDetail/FetchScript/FetchWord/Delete)들이 추가되었습니다.
모델(코어)
core/model/...
프레젠테이션 관련 도메인 모델(PresentationInfo, PresentationAnalysisSummary, PresentationScriptDetail, PresentationWordDetail, PresentationAnalysisRequest)과 연관 enum(Style/Category/Purpose/Audience) 및 연습 속도(RecordingSpeed) 정의·변경이 적용되었습니다. 기존 Presentation 및 일부 이전 분석 타입은 제거되었습니다.
네트워크: 서비스·DTO·클라이언트
core/network/service/*, core/network/model/presentation/*, core/network/client/HttpClientFactory.kt
Ktorfit PresentationService 인터페이스 및 여러 응답 DTO(PresentationSummaryResponse, PresentationScriptDetailResponse, PresentationWordDetailResponse, GetPresentationsResponse, GetPresentationDetailResponse)를 추가했고 HttpClient에 HttpTimeout 설치와 설정을 도입했습니다.
네트워크: 원격 데이터소스 구현·DI
core/network/.../PresentationRemoteDataSource*, core/network/di/*
PresentationRemoteDataSource/PresentationRemoteDataSourceImpl 추가(멀티파트 업로드 유틸 포함)하고 Hilt 바인딩 및 providePresentationService 제공자를 등록했습니다.
데이터 레이어: 매퍼·리포지토리·오류 매핑
core/data/...
PresentationMapper로 DTO→도메인 매핑 추가, PresentationRepositoryImpl 구현 및 Hilt 바인딩 추가, AppError 매핑에 새로운 서버 에러 코드(PRESENTATION_NOT_FOUND, ANALYSIS_RESULT_NOT_FOUND) 처리와 CancellationException 보존 로직을 반영했습니다.
플랫 변경: 빌드·설정
app/build.gradle.kts, core/data/build.gradle.kts, feature module build files
앱·모듈의 의존성에 report 모듈/코어 의존성·kotlinx.datetime 등을 추가하고 일부 테스트 옵션이 정리되었습니다.
분석 플로우 및 연관 UI 변경
feature/analysis/impl/...
분석 UseCase를 Presentation 중심으로 전환했고, AnalysisFlow 뷰모델·스크린에서 Report 단계가 제거되고 NavigateToReport 이펙트로 대체되어 보고서 네비게이션을 호출하도록 변경했습니다.
리포트 기능(신규)
feature/report/impl/...
분석 리포트 화면(AnalysisReportScreen), 뷰모델(AssistedFactory), UI 레이아웃(ReportScreenLayout), 섹션(Accuracy/Growth/Script/ExpectedQuestions/Summary/SelfFeedback 등), 상태·이펙트·인텐트·매퍼·프리뷰 등 리포트 전반을 새로 구현했습니다.
히스토리/홈 연동
feature/history/impl/..., feature/home/impl/...
히스토리·홈의 모델 변환을 PresentationInfo로 전환하고 내비게이션 콜백을 통해 ReportNavKey로 이동하도록 연동했습니다. 히스토리 뷰모델은 upcoming/past use case를 병렬 호출해 상태를 구성합니다.
디자인시스템·네비게이션 미세조정
core/designsystem/..., core/navigation/Navigator.kt
아이콘 프로퍼티 추가, PrezelIconButton에 isUseRipple 파라미터 추가, 리스트 타이틀 maxLines 제거 등 UI 컴포넌트 조정과 Navigator.navigate에 clearStack 파라미터 및 하위 스택 정리 로직이 추가되었습니다.

Possibly related PRs

* **ui: AnalysisReportScreen 내 스낵바 위치 옵션 수정**
    * `AnalysisReportUiEffect.ShowMessage` 처리 시 `showPrezelSnackbar`에 `useRaisedPosition = false` 파라미터를 추가하여 스낵바 노출 위치를 조정했습니다.
Copy link
Copy Markdown
Contributor

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

Caution

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

⚠️ Outside diff range comments (1)
Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/AnalysisFlowViewModel.kt (1)

100-123: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

runCatchingCancellationException을 실패로 바꿔 UI에 부수효과를 유발합니다.

analyzePresentationRecording()에서 runCatchingCancellationException까지 캡처하면 analyzeJob?.cancel()로 취소된 요청도 onFailure로 흘러 handleAnalysisFailure(throwable.toAnalysisFailureAction())가 실행됩니다. Throwable.toAnalysisFailureAction()CancellationException처럼 AppException이 아닌 경우 UNKNOWN_FAILED 메시지(및 AUDIO_UPLOAD 단계 전환)를 발생시켜 취소 흐름이 깨질 수 있습니다. 취소는 반드시 재전파해 주세요.

🔧 제안 수정안
+import kotlinx.coroutines.CancellationException
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.launch
@@
 private suspend fun PresentationAnalysisSubmission.analyzePresentationRecording(): Result<Long> =
     runCatching {
@@
             ).getOrThrow()
-        }
+        }.onFailure { throwable ->
+            if (throwable is CancellationException) throw throwable
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/AnalysisFlowViewModel.kt`
around lines 100 - 123, The runCatching in analyzePresentationRecording() is
capturing CancellationException and turning cancellations into failures; change
the error handling so CancellationException always rethrows instead of being
treated as a normal failure. Concretely, in
PresentationAnalysisSubmission.analyzePresentationRecording() (the runCatching
block that calls analyzePresentationUseCase), ensure any caught Throwable that
is a CancellationException is rethrown immediately (or avoid wrapping the call
in runCatching and use a try/catch that rethrows CancellationException), while
still capturing/returning other exceptions as Result failures so downstream code
(e.g., handleAnalysisFailure) doesn’t run for cancellations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Prezel/core/data/src/main/java/com/team/prezel/core/data/repository/PresentationRepositoryImpl.kt`:
- Around line 32-106: The mapDomainFailure() extension in AppErrorExt.kt
currently wraps all Throwables via toDomainThrowable() (producing
AppException(UNKNOWN) for else) which swallows CancellationException; modify
mapDomainFailure() so it first checks if the caught Throwable is a
kotlin.coroutines.cancellation.CancellationException (or
java.util.concurrent.CancellationException) and if so rethrow it immediately,
otherwise continue converting via toDomainThrowable() and returning
Result.failure(AppException/...); update the function that invokes
toDomainThrowable() (mapDomainFailure) to include this early-return rethrow
branch to preserve coroutine cancellation propagation.

In
`@Prezel/core/model/src/main/java/com/team/prezel/core/model/practice/PracticeRecordingAnalysisResult.kt`:
- Around line 18-21: The from method (PracticeRecordingOverallEvaluation.from)
currently compares entry.value to value.uppercase(), which depends on the JVM
default Locale; change this to a locale-independent comparison by using a
Locale-root uppercase conversion (e.g., value.uppercase(Locale.ROOT)) or use a
case-insensitive comparison (e.g., equalsIgnoreCase) to ensure stable matching;
apply the same change to the other similar factory methods
(Purpose/Style/Category/Audience) that use value.uppercase() so all enum parsing
is locale-independent.

In
`@Prezel/core/network/src/main/java/com/team/prezel/core/network/client/HttpClientFactory.kt`:
- Around line 92-100: The installLogging() function in HttpClientFactory.kt
currently only calls sanitizeHeader when !BuildConfig.DEBUG, leaving
Authorization unmasked in debug builds; move the sanitizeHeader { header ->
header == HttpHeaders.Authorization } call out of the if (!BuildConfig.DEBUG)
block so it runs unconditionally (i.e., keep logger = KtorPrettyLogger and level
logic as-is but ensure sanitizeHeader is invoked for both debug and release
within the Logging install block) to always mask Authorization headers.

In
`@Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PracticeRemoteDataSourceImpl.kt`:
- Around line 48-51: File.toChannelProvider() currently opens inputStream()
lazily which defers file-not-found/read errors; add an early check for file
accessibility (e.g. call exists() and canRead() on the File) inside
toChannelProvider() and throw a clear exception (or return a failed result) if
the checks fail before creating the ChannelProvider, so callers of
File.toChannelProvider() get immediate, descriptive failures instead of late
inputStream() errors.

In
`@Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PresentationRemoteDataSourceImpl.kt`:
- Around line 46-48: Validate file paths and accessibility before creating
multipart parts: ensure scriptFilePath is non-empty and points to an existing,
readable regular file and verify audioPath used in reAnalyzePresentation
similarly (check non-empty, exists, isFile, readable and optionally
MIME/extension) before calling appendTextPart or opening inputStream(); if
validations fail, return or throw a clear error and log context (include path
and reason) to avoid delayed runtime exceptions when inputStream() is invoked.

In
`@Prezel/core/network/src/main/java/com/team/prezel/core/network/service/PresentationService.kt`:
- Around line 49-55: In PresentationService.kt the `@GET` annotations for
getUpcomingPresentationDetail and getPastPresentationDetail use leading slashes
(e.g. `@GET`("/recording/...")) which override the BASE_URL path prefix; remove
the leading '/' so they become relative paths (e.g. `@GET`("recording/...")) to
preserve BuildConfig.BASE_URL (which may include /api/v1); update those two
methods' annotations and scan other `@GET/`@POST entries in PresentationService to
ensure none use a leading slash.

In
`@Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/HistoryViewModel.kt`:
- Around line 38-51: The current code awaits upcomingDeferred and pastDeferred
separately and calls
sendEffect(HistoryUiEffect.ShowMessage(HistoryUiMessage.FETCH_DATA_FAILED))
inside each onFailure branch, which can emit the same error effect twice; change
the logic in HistoryViewModel so you collect the success/failure of both awaited
calls first (e.g., await both deferreds, or use awaitAll/zip) and then map
successes to UI models for upcoming and past, and if either or both failed send
a single
sendEffect(HistoryUiEffect.ShowMessage(HistoryUiMessage.FETCH_DATA_FAILED)) once
after evaluating both results (use upcomingDeferred and pastDeferred result
containers rather than calling sendEffect inside each onFailure).

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportViewModel.kt`:
- Around line 73-77: The when-branches for AnalysisReportDialog.RE_RECORDING and
RE_WRITE_SCRIPT currently return Unit so nothing happens; replace those Unit
branches with calls to the appropriate handler methods (e.g., call a re-record
handler like startReRecording() or reRecordPresentation() for RE_RECORDING and a
script rewrite handler like startRewriteScript() or rewritePresentationScript()
for RE_WRITE_SCRIPT), ensure those methods exist on AnalysisReportViewModel and
perform the necessary navigation/effect or emit the proper event, and keep the
DELETE_REPORT branch calling deletePresentation() unchanged.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt`:
- Around line 23-41: SelfFeedbackSection currently renders a "write feedback"
PrezelTextButton with an empty onClick handler, so the button does nothing;
change SelfFeedbackSection to accept a callback parameter (e.g.,
onWriteFeedback: () -> Unit) and forward that callback to the PrezelTextButton's
onClick instead of using onClick = {}, updating all call sites of
SelfFeedbackSection to provide the action; ensure the function signature and the
PrezelTextButton invocation (names: SelfFeedbackSection, PrezelTextButton,
onClick) are modified accordingly.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/common/ReportMetricCards.kt`:
- Around line 68-71: toPercentLabel() currently builds the string
unconditionally appending "%" so a null Double yields "-%"; change the function
(Double?.toPercentLabel) to branch on null: if this is null return "-" (no
percent sign), otherwise roundToInt() and return the numeric value with "%"
appended (e.g., "${base}%") so null results in "-" and non-null results like
"42%".

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/modal/ReportDialog.kt`:
- Around line 22-26: The dialog currently ignores system dismiss because
PrezelDialog is hardcoded with onDismiss = {}; update the ReportDialog
composable to pass the received onDismissClick handler into PrezelDialog
(replace onDismiss = {} with onDismiss = onDismissClick) so system/back press
and outside-tap dismisses invoke the provided callback; ensure the symbol names
to change are PrezelDialog and the onDismissClick parameter in ReportDialog.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/GrowthGraphData.kt`:
- Around line 27-30: The require check currently allows selectedItemIndex in
0..items.size which permits an off-by-one value that makes selectedItem
(items.getOrNull(selectedItemIndex)) become null; change the validation in the
require call to enforce valid indices (use items.indices) and, if empty lists
should be handled specially, add an explicit check that throws when
items.isEmpty() before validating selectedItemIndex; update the require on
selectedItemIndex and any logic referencing selectedItemIndex/selectedItem
accordingly.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt`:
- Around line 22-23: 현재 ReportEntryBuilder에 전달된 navigateToAnalysisScript 및
navigateToAnalysisRecording가 빈 람다여서 해당 이펙트가 발생해도 화면 이동이 이루어지지 않습니다; 수정하려면
ReportEntryBuilder를 호출하는 곳에서 navigateToAnalysisScript 및
navigateToAnalysisRecording 인자로 실제 네비게이션 로직(예: NavController.navigate 호출 또는 상위의
navigator.invoke 등)을 전달하도록 교체하고, ReportEntryBuilder 내부에서 이 콜백들을 그대로 호출하도록 유지하여
다시 대본쓰기/다시 녹음하기 액션이 실제 화면 전환으로 연결되게 하세요 (참조 심볼: navigateToAnalysisScript,
navigateToAnalysisRecording, ReportEntryBuilder).

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/preview/ReportPreviewUiState.kt`:
- Around line 64-66: ReportPreviewUpcomingUiState currently references
ReportPreviewPastUiState (so isPast=true); change it to use the base preview
with isPast=false instead. Replace the assignment of
ReportPreviewUpcomingUiState that points to ReportPreviewPastUiState with a copy
of ReportPreviewBaseUiState (e.g., ReportPreviewBaseUiState.copy(isPast =
false)) so upcoming state is independent and has isPast = false; ensure you
update the symbol ReportPreviewUpcomingUiState only.

---

Outside diff comments:
In
`@Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/AnalysisFlowViewModel.kt`:
- Around line 100-123: The runCatching in analyzePresentationRecording() is
capturing CancellationException and turning cancellations into failures; change
the error handling so CancellationException always rethrows instead of being
treated as a normal failure. Concretely, in
PresentationAnalysisSubmission.analyzePresentationRecording() (the runCatching
block that calls analyzePresentationUseCase), ensure any caught Throwable that
is a CancellationException is rethrown immediately (or avoid wrapping the call
in runCatching and use a try/catch that rethrows CancellationException), while
still capturing/returning other exceptions as Result failures so downstream code
(e.g., handleAnalysisFailure) doesn’t run for cancellations.
🪄 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: de56e9e5-720b-4284-9c70-660d8b8e4f21

📥 Commits

Reviewing files that changed from the base of the PR and between 66275e0 and 8eb2e3f.

📒 Files selected for processing (114)
  • Prezel/app/build.gradle.kts
  • Prezel/core/data/build.gradle.kts
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/di/RepositoryModule.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/error/AppErrorExt.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/mapper/PracticeMapper.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/mapper/PresentationMapper.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/repository/PracticeRepositoryImpl.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/repository/PresentationRepositoryImpl.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/actions/button/PrezelIconButton.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/list/PrezelList.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt
  • Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_script.xml
  • Prezel/core/designsystem/src/main/res/drawable/core_designsystem_ic_top_right.xml
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/repository/practice/PracticeRepository.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/repository/presentation/PresentationRepository.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/AnalyzePresentationUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/DeletePresentationAnalysisUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/FetchPastPresentationsUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/FetchPresentationDetailUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/FetchPresentationScriptDetailUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/FetchPresentationWordDetailUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/FetchUpcomingPresentationsUseCase.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/usecase/presentation/ReAnalyzePresentationUseCase.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/practice/PracticeRecordingAnalysisResult.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/practice/RecordingSpeed.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Audience.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Category.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Presentation.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationAnalysisRequest.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationAnalysisSummary.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationInfo.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationRecordingAnalysisResult.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationScriptDetail.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationWordDetail.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Purpose.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Style.kt
  • Prezel/core/navigation/src/main/java/com/team/prezel/core/navigation/Navigator.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/client/HttpClientFactory.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PracticeRemoteDataSource.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PracticeRemoteDataSourceImpl.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PresentationRemoteDataSource.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PresentationRemoteDataSourceImpl.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/di/DataSourceModule.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/di/NetworkModule.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/model/BaseResponse.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/model/presentation/GetPresentationDetailResponse.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/model/presentation/GetPresentationsResponse.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/model/presentation/PresentationScriptDetailResponse.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/model/presentation/PresentationSummaryResponse.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/model/presentation/PresentationWordDetailResponse.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/service/PresentationService.kt
  • Prezel/feature/analysis/impl/build.gradle.kts
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/AnalysisFlowViewModel.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/AnalysisScreen.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/contract/AnalysisFlowUiEffect.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/contract/AnalysisFlowUiState.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/navigation/AnalysisEntryBuilder.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/result/AnalysisReportScreen.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/situation/PresentationSituationScreen.kt
  • Prezel/feature/history/impl/build.gradle.kts
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/HistoryScreen.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/HistoryViewModel.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/component/HistoryItemList.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/component/HistoryPresentationCard.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/contract/HistoryUiEffect.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/contract/HistoryUiIntent.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/contract/HistoryUiState.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/model/HistoryUiModel.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/navigation/HistoryEntryBuilder.kt
  • Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/HomeViewModel.kt
  • Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/model/PresentationUiModel.kt
  • Prezel/feature/practice/impl/src/main/java/com/team/prezel/feature/practice/impl/analysis/PracticeAnalysisScreen.kt
  • Prezel/feature/practice/impl/src/main/java/com/team/prezel/feature/practice/impl/analysis/component/PracticeAnalysisResultPage.kt
  • Prezel/feature/practice/impl/src/main/java/com/team/prezel/feature/practice/impl/analysis/contract/PracticeAnalysisUiState.kt
  • Prezel/feature/report/api/src/main/java/com/team/prezel/feature/report/api/ReportNavKey.kt
  • Prezel/feature/report/api/src/test/java/com/team/prezel/feature/report/api/.gitkeep
  • Prezel/feature/report/impl/build.gradle.kts
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportScreen.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportViewModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/ReportScreen.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/ReportViewModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/ReportBodyContent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/ReportHeaderContent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/ReportScreenLayout.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/AccuracySection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/ExpectedQuestionsSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/GrowthGraphSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/PracticeHistorySection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/ScriptAnalysisSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SummaryFeedbackSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/common/EmptyStateCard.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/common/ReportMetricCards.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/common/ReportSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/modal/ReportDialog.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/AnalysisReportUiEffect.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/AnalysisReportUiIntent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/AnalysisReportUiState.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/AnalysisReportUiStateMapper.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/ReportUiEffect.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/ReportUiIntent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/ReportUiState.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/AnalysisReportDialog.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/AnalysisReportUiMessage.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/GrowthGraphData.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/PracticeUiModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/PresentationInfoUiModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/QuestionUiModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/ScriptAnalysisGraphData.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/model/SpeedGraphData.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/preview/ReportPreviewUiState.kt
  • Prezel/feature/report/impl/src/main/res/values/strings.xml
  • Prezel/feature/report/impl/src/test/java/com/team/prezel/feature/report/impl/.gitkeep
💤 Files with no reviewable changes (13)
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/ReportUiState.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/ReportUiEffect.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Presentation.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationRecordingAnalysisResult.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/result/AnalysisReportScreen.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/ReportScreen.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/ReportUiIntent.kt
  • Prezel/core/domain/src/main/kotlin/com/team/prezel/core/domain/repository/practice/PracticeRepository.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/ReportViewModel.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PracticeRemoteDataSource.kt
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/repository/PracticeRepositoryImpl.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/list/PrezelList.kt
  • Prezel/feature/analysis/impl/src/main/java/com/team/prezel/feature/analysis/impl/contract/AnalysisFlowUiState.kt

- `ReportSection`, `AccuracySection`, `GrowthGraphSection` 등 주요 섹션의 타이틀 텍스트 스타일을 `body2Bold`에서 `title2Bold`로 변경
- `AccuracySection` 내 설명 텍스트의 스타일 및 색상을 `body3Regular`, `textRegular`로 수정
- `GrowthGraphSection` 타이틀 영역의 수직 정렬(`CenterVertically`) 추가
- `ExpectedQuestionsSection`에서 질문 목록 사이의 구분선(`divider`) 표시 로직 추가
- `ReportBodyContent`의 초기 상태 설정에 `selectedItemIndex` 값 명시
- `PrezelIcons` 내 `ArrowTopRight` 리소스 파일 이름 변경 반영 (`ic_top_right` -> `ic_arrow_top_right`)
- 불필요한 `core_designsystem_ic_top_right.xml` 파일 삭제 및 `ic_script` 벡터 이미지 코드 정리 (Copyright 주석 제거 및 포맷팅)
- `id`를 `presentationId`로, `date`를 `presentationDate`로 변경하여 의미를 명확화
- `dDay` 타입을 `Int`에서 `String`으로 변경하고 UI 모델 생성 시점에 라벨을 확정하도록 수정
- `HistoryUiModel` 내부에 존재하던 `dDayLabel` 계산 로직 제거
- `HistoryViewModel`, `HistoryScreen` 등 관련 컴포포넌트의 식별자 참조 로직 수정
- Preview 데이터를 변경된 모델 구조에 맞춰 업데이트
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt (1)

23-40: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

빈 상태 CTA가 동작하지 않습니다.

Line 39의 onClick = {} 때문에 “피드백 작성” 버튼이 실제로 아무 작업도 수행하지 않습니다. 콜백 파라미터를 받아 연결해 주세요.

수정 예시
-internal fun SelfFeedbackSection(selfFeedback: String?) {
+internal fun SelfFeedbackSection(
+    selfFeedback: String?,
+    onWriteFeedbackClick: () -> Unit,
+) {
@@
-                onClick = {},
+                onClick = onWriteFeedbackClick,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt`
around lines 23 - 40, The empty CTA handler is non-functional because
SelfFeedbackSection currently uses a no-op lambda (onClick = {}) for the
PrezelTextButton; update the API to accept a callback and wire it through:
change the SelfFeedbackSection signature to take a parameter like
onWriteFeedback: () -> Unit, replace the no-op in the PrezelTextButton onClick
with that parameter, and ensure any callers of SelfFeedbackSection pass the
appropriate callback so the “피드백 작성” button actually triggers the intended
action.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt`:
- Around line 23-40: The empty CTA handler is non-functional because
SelfFeedbackSection currently uses a no-op lambda (onClick = {}) for the
PrezelTextButton; update the API to accept a callback and wire it through:
change the SelfFeedbackSection signature to take a parameter like
onWriteFeedback: () -> Unit, replace the no-op in the PrezelTextButton onClick
with that parameter, and ensure any callers of SelfFeedbackSection pass the
appropriate callback so the “피드백 작성” button actually triggers the intended
action.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 78f3a3ca-ffaa-442f-89c9-5e7df1ac9d3c

📥 Commits

Reviewing files that changed from the base of the PR and between 8eb2e3f and 761b616.

📒 Files selected for processing (15)
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/HistoryScreen.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/HistoryViewModel.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/component/HistoryItemList.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/component/HistoryPresentationCard.kt
  • Prezel/feature/history/impl/src/main/java/com/team/prezel/feature/history/impl/model/HistoryUiModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportScreen.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/ReportBodyContent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/AccuracySection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/ExpectedQuestionsSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/GrowthGraphSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/ScriptAnalysisSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SummaryFeedbackSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/common/ReportSection.kt
✅ Files skipped from review due to trivial changes (1)
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/PrezelIcons.kt

moondev03 added 7 commits May 26, 2026 16:02
* **fix: `toDomainThrowable`에서 `CancellationException` 보존**
    * 에러 매핑 함수인 `toDomainThrowable`에서 `CancellationException`이 발생했을 때 이를 `AppException` 등 다른 에러 타입으로 변환하지 않고 그대로 반환하도록 수정했습니다.
    * 이를 통해 코루틴의 취소(Cancellation) 신호가 유실되지 않고 상위 호출부로 정상적으로 전달되도록 보장합니다.
* **refactor: `from` 팩토리 메서드 내 대소문자 무시 비교 로직 수정**
    * `Style`, `Category`, `Purpose`, `Audience`, `PracticeRecordingOverallEvaluation` 클래스의 `from` 메서드에서 기존 `uppercase()` 변환 후 비교하던 방식을 `equals(ignoreCase = true)` 사용으로 변경했습니다.
    * 문자열 비교 시 대소문자 구분을 안정적으로 처리하고 코드를 더 간결하게 개선했습니다.
* **refactor: `Authorization` 헤더 마스킹 정책 변경**
    * 로그를 통한 인증 토큰 노출을 방지하기 위해, 기존에 디버그 모드가 아닐 때만 적용하던 `sanitizeHeader` 설정을 빌드 환경과 상관없이 항상 적용하도록 변경했습니다.

* **style: 코드 포맷팅 수정**
    * `isSessionInvalidForReissue` 함수 내 `errorCode` 리스트의 들여쓰기를 수정하여 가독성을 개선했습니다.
* **refactor: 파일 스트림 생성 시 유효성 검증 로직 추가**
    * `PracticeRemoteDataSourceImpl` 및 `PresentationRemoteDataSourceImpl`에서 파일을 `ChannelProvider`로 변환할 때, 파일의 존재 여부(`exists`)와 읽기 권한(`canRead`)을 검증하는 `require` 구문을 추가했습니다.

* **refactor: `PresentationRemoteDataSourceImpl` 내 멀티파트 요청 로직 개선**
    * `appendTextPart` 메서드를 역할이 명확하도록 `appendScriptPart`로 이름을 변경했습니다.
    * 스크립트 파일 경로(`scriptFilePath`) 처리 시, 단순 null 체크 외에 `isNotBlank()` 검증을 추가하여 빈 경로가 전달되지 않도록 개선했습니다.
    * 멀티파트 폼 데이터 구성 시 파라미터 추가 순서를 조정했습니다.
* **fix: API 엔드포인트 경로의 불필요한 선행 슬래시 제거**
    * `PresentationService` 인터페이스 내 `getUpcomingPresentationDetail` 및 `getPastPresentationDetail` 메서드의 `@GET` 어노테이션 경로에서 선행 슬래시(`/`)를 제거하여 상대 경로 형식을 통일했습니다.
* **feat: `AnalysisReportViewModel` 내 다이얼로그 확인 액션 연동**
    * `handleDialogConfirm` 메서드에서 기존에 비어있던(`Unit`) `RE_RECORDING` 및 `RE_WRITE_SCRIPT` 케이스에 대한 처리 로직을 추가했습니다.
    * 다이얼로그 확인 시 각각 재녹음 및 대본 수정 화면으로 이동하도록 개선했습니다.

* **feat: 화면 이동을 위한 Navigation Effect 전송 로직 추가**
    * `navigateToAnalysisRecording` 및 `navigateToAnalysisScript` 메서드를 구현하여 `presentationId` 존재 여부 확인 후 `AnalysisReportUiEffect`를 전송합니다.
    * `viewModelScope`를 사용하여 비동기적으로 네비게이션 이벤트를 처리하도록 구성했습니다.
* **feat: 셀프 피드백 작성을 위한 UI Intent 및 Effect 추가**
    * 사용자가 피드백 작성을 요청할 때 발생하는 `AnalysisReportUiIntent.ClickFeedbackWrite`를 추가했습니다.
    * 해당 Intent 처리 시 화면 전환을 위한 `AnalysisReportUiEffect.NavigateToSelfFeedbackWrite` 이벤트를 정의했습니다.

* **feat: UI 컴포넌트 레이어의 클릭 이벤트 전파 로직 구현**
    * `SelfFeedbackSection` 컴포넌트에 `onFeedBackWriteClick` 콜백을 추가하여 버튼 클릭 이벤트를 상위로 전달하도록 수정했습니다.
    * `AnalysisReportScreen`부터 `ReportBodyContent`를 거쳐 최하위 버튼까지 클릭 이벤트를 전달하는 인터페이스를 구성했습니다.
    * `AnalysisReportScreen`의 `LaunchedEffect`에서 네비게이션 Effect 발생 시 실제 화면 전환 함수가 호출되도록 연동했습니다.

* **refactor: `AnalysisReportViewModel` 내 네비게이션 및 로직 구조 개선**
    * `presentationId` 유무 확인 후 Effect를 전송하는 로직을 Kotlin idiomatic 패턴(`let`, `?: return`)을 사용하여 간결하게 리팩터링했습니다.
    * 스크립트 재작성 및 녹화 화면 이동 로직을 별도 메서드로 추출하여 코드 중복을 제거했습니다.

* **build: 네비게이션 엔트리 포인트 업데이트**
    * `AnalysisReportScreen`의 파라미터가 추가됨에 따라 `ReportEntryBuilder` 내의 호출 코드를 업데이트했습니다.
Copy link
Copy Markdown
Contributor

@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)
Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportViewModel.kt (1)

71-79: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

확인 액션에서 다이얼로그 상태를 먼저 정리해 주세요.

Line 74-77 분기에서 이동/삭제를 실행하기 전에 reportDialognull로 초기화하지 않아, 뒤로 돌아왔을 때 동일 다이얼로그가 남아 재노출될 수 있습니다.

수정 예시
 private fun handleClickDialogConform() {
     val dialog = contentState?.reportDialog ?: return
+    updateContent { copy(reportDialog = null) }

     when (dialog) {
         AnalysisReportDialog.RE_RECORDING -> navigateToAnalysisRecording()
         AnalysisReportDialog.RE_WRITE_SCRIPT -> navigateToAnalysisScript()
         AnalysisReportDialog.DELETE_REPORT -> deletePresentation()
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportViewModel.kt`
around lines 71 - 79, The dialog state (contentState.reportDialog) must be
cleared before performing navigation or deletion to avoid the same dialog
reappearing; in handleClickDialogConform(), first set reportDialog to null
(e.g., via the existing state updater or a
clearReportDialog()/updateContentState call) and only then call
navigateToAnalysisRecording(), navigateToAnalysisScript(), or
deletePresentation() so the UI state is reset prior to actions.
♻️ Duplicate comments (1)
Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt (1)

22-24: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

네비게이션 콜백이 여전히 no-op이라 액션 플로우가 끊깁니다.

Line 22-24에서 navigateToAnalysisScript, navigateToAnalysisRecording, navigateToSelfFeedbackWrite가 모두 빈 람다라, ViewModel 이펙트가 발생해도 실제 화면 이동이 실행되지 않습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt`
around lines 22 - 24, The three navigation callbacks in ReportEntryBuilder
(navigateToAnalysisScript, navigateToAnalysisRecording,
navigateToSelfFeedbackWrite) are currently no-op lambdas so ViewModel effects
never trigger navigation; replace the empty lambdas with real navigation
handlers by wiring them to the app's navigation actions (e.g., call the
NavController navigate destinations or invoke the higher-level navigation
functions you pass into ReportEntryBuilder) and ensure the ViewModel effect
consumer calls these callbacks; update ReportEntryBuilder's construction sites
to pass the proper navigation functions instead of {} so the effects result in
actual screen transitions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PresentationRemoteDataSourceImpl.kt`:
- Around line 120-124: File.toChannelProvider() currently only checks exists()
and canRead(), which lets directories pass; add a require(isFile()) check before
creating the ChannelProvider to ensure the path is a regular file. Update the
require message to something like "정규 파일이 아닙니다: $path" (or similar) and place it
alongside the existing requires in the File.toChannelProvider() function so
ChannelProvider(size = length()) is only invoked for actual files.

---

Outside diff comments:
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportViewModel.kt`:
- Around line 71-79: The dialog state (contentState.reportDialog) must be
cleared before performing navigation or deletion to avoid the same dialog
reappearing; in handleClickDialogConform(), first set reportDialog to null
(e.g., via the existing state updater or a
clearReportDialog()/updateContentState call) and only then call
navigateToAnalysisRecording(), navigateToAnalysisScript(), or
deletePresentation() so the UI state is reset prior to actions.

---

Duplicate comments:
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt`:
- Around line 22-24: The three navigation callbacks in ReportEntryBuilder
(navigateToAnalysisScript, navigateToAnalysisRecording,
navigateToSelfFeedbackWrite) are currently no-op lambdas so ViewModel effects
never trigger navigation; replace the empty lambdas with real navigation
handlers by wiring them to the app's navigation actions (e.g., call the
NavController navigate destinations or invoke the higher-level navigation
functions you pass into ReportEntryBuilder) and ensure the ViewModel effect
consumer calls these callbacks; update ReportEntryBuilder's construction sites
to pass the proper navigation functions instead of {} so the effects result in
actual screen transitions.
🪄 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: 48934854-4bcf-42a2-bf71-a958a702fa23

📥 Commits

Reviewing files that changed from the base of the PR and between 761b616 and a266937.

📒 Files selected for processing (18)
  • Prezel/core/data/src/main/java/com/team/prezel/core/data/error/AppErrorExt.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/practice/PracticeRecordingAnalysisResult.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Audience.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Category.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Purpose.kt
  • Prezel/core/model/src/main/java/com/team/prezel/core/model/presentation/Style.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/client/HttpClientFactory.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PracticeRemoteDataSourceImpl.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/datasource/PresentationRemoteDataSourceImpl.kt
  • Prezel/core/network/src/main/java/com/team/prezel/core/network/service/PresentationService.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportScreen.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/AnalysisReportViewModel.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/ReportBodyContent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/ReportScreenLayout.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/component/body/SelfFeedbackSection.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/AnalysisReportUiEffect.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/contract/AnalysisReportUiIntent.kt
  • Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt

@moondev03 moondev03 merged commit c7dc878 into develop May 26, 2026
2 checks passed
@moondev03 moondev03 deleted the feat/#134-분석-리포트-화면-구현 branch May 26, 2026 10:29
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.

분석 리포트 화면 구현 아카이브 화면 API 연동

2 participants