Skip to content

Flt 22 컬렉션 신고 UI 제작#215

Merged
chanmi1125 merged 10 commits into
developfrom
FLT-22-컬렉션-신고-UI-제작
Jun 18, 2026

Hidden character warning

The head ref may contain hidden characters: "FLT-22-\uceec\ub809\uc158-\uc2e0\uace0-UI-\uc81c\uc791"
Merged

Flt 22 컬렉션 신고 UI 제작#215
chanmi1125 merged 10 commits into
developfrom
FLT-22-컬렉션-신고-UI-제작

Conversation

@chanmi1125

@chanmi1125 chanmi1125 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

📮 관련 이슈

  • closed #이슈번호

📌 작업 내용

  • 컬렉션 신고를 구현합니다

📸 스크린샷

스크린샷

😅 미구현

  • [ ]

🫛 To. 리뷰어

Summary by CodeRabbit

릴리스 노트

  • 새 기능
    • 컬렉션 신고 기능이 추가되었습니다. 사용자는 이제 컬렉션 상세 페이지에서 신고 버튼을 통해 신고 화면으로 이동할 수 있습니다.
    • 신고 사유 선택 (폭력, 음란물, 스팸, 저작권, 기타) 및 추가 상세 내용 입력이 가능합니다.
    • 신고 제출 성공 시 확인 알림이 표시됩니다.

@chanmi1125 chanmi1125 self-assigned this Jun 17, 2026
@chanmi1125 chanmi1125 added 🔖 API feat - API 연동 🧩 Component feat - 공통 컴포넌트 작업 Feat ✨ 신규 기능을 추가하거나 기존 기능의 동작, 정책을 변경 labels Jun 17, 2026
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@chanmi1125, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 44 minutes and 16 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ebc302d3-e295-479f-af2f-bedddd9dbb95

📥 Commits

Reviewing files that changed from the base of the PR and between 3f6b3a3 and d94a58c.

📒 Files selected for processing (3)
  • app/src/main/java/com/flint/presentation/collectiondetail/report/CollectionReportScreen.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportCheck.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportTopAppBar.kt
📝 Walkthrough

Walkthrough

컬렉션 신고(Report) 기능을 전체 스택으로 추가한다. 데이터 레이어에 신고 요청 DTO·모델·매퍼·API 엔드포인트·레포지토리 메서드를 신설하고, 프레젠테이션 레이어에 신고 화면 Compose UI·ViewModel·네비게이션을 추가하며, CollectionDetailRouteMainNavHost에 신고 라우트와 성공 토스트를 연결한다.

Changes

컬렉션 신고 기능 전체 스택

Layer / File(s) Summary
신고 요청 데이터 계층
com/flint/domain/model/collection/CollectionReportModel.kt, com/flint/data/dto/collection/request/CollectionReportRequestDto.kt, com/flint/domain/mapper/collection/CollectionReportMapper.kt, com/flint/data/api/CollectionApi.kt, com/flint/domain/repository/CollectionRepository.kt
CollectionReportRequestModelCollectionReportRequestDto를 신설하고 toDto() 매퍼로 연결한다. CollectionApiPOST /api/v1/collections/{collectionId}/reports 엔드포인트를 추가하고 CollectionRepository가 모델을 DTO로 변환해 호출한 뒤 Result<Unit>을 반환한다.
신고 화면 ViewModel 및 UI 상태
com/flint/presentation/collectiondetail/report/ReportReason.kt, com/flint/presentation/collectiondetail/report/CollectionReportUiState.kt, com/flint/presentation/collectiondetail/report/CollectionReportViewModel.kt
ReportReason enum(5개 신고 사유), CollectionReportUiState(선택 사유·텍스트·로딩), CollectionReportSideEffect(성공/실패), CollectionReportViewModel(선택·입력·제출·중복 방지 로직)을 추가한다.
신고 화면 Compose UI
com/flint/presentation/collectiondetail/report/component/ReportTopAppBar.kt, com/flint/presentation/collectiondetail/report/component/ReportCheck.kt, com/flint/presentation/collectiondetail/report/component/ReportBottomSection.kt, com/flint/presentation/collectiondetail/report/CollectionReportScreen.kt
상단 앱바(ReportTopAppBar), 신고 사유 체크 목록+텍스트 입력(ReportCheck, ReportCheckItem), 정보 안내+제출 버튼(ReportBottomSection)을 구현하고, CollectionReportRoute에서 ViewModel 상태를 구독해 화면을 조합한다.
신고 화면 네비게이션 및 기존 화면 연결
com/flint/presentation/collectiondetail/report/navigation/CollectionReportNavigation.kt, com/flint/presentation/collectiondetail/CollectionDetailScreen.kt, com/flint/presentation/collectiondetail/navigation/CollectionDetailNavigation.kt, com/flint/presentation/main/MainNavigator.kt, com/flint/presentation/main/MainNavHost.kt
collectionReportNavGraphnavigateToCollectionReport 확장 함수를 추가하고, CollectionDetailRouteonReportClick을 실제 네비게이션 호출로 교체한다. MainNavHost에 신고 라우트를 등록하고 savedStateHandle을 통해 성공 토스트를 표시한다.

Sequence Diagram(s)

sequenceDiagram
  actor 사용자
  participant CollectionDetailScreen
  participant CollectionReportScreen
  participant CollectionReportViewModel
  participant CollectionRepository
  participant CollectionApi

  사용자->>CollectionDetailScreen: 신고 버튼 클릭
  CollectionDetailScreen->>CollectionReportScreen: navigateToCollectionReport(collectionId)
  사용자->>CollectionReportScreen: 신고 사유 선택 및 제출
  CollectionReportScreen->>CollectionReportViewModel: submitReport()
  CollectionReportViewModel->>CollectionRepository: postCollectionReport(collectionId, model)
  CollectionRepository->>CollectionApi: POST /collections/{collectionId}/reports
  CollectionApi-->>CollectionRepository: BaseEmptyResponse
  CollectionRepository-->>CollectionReportViewModel: Result.success(Unit)
  CollectionReportViewModel-->>CollectionReportScreen: SideEffect: ReportSuccess
  CollectionReportScreen->>CollectionDetailScreen: navigateUpWithSuccess()
  CollectionDetailScreen->>CollectionDetailScreen: 신고 접수 토스트 표시
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • imflint/Flint-Android#213: 동일하게 컬렉션 신고 흐름을 CollectionDetail에서 Route.CollectionReport로 연결하는 네비게이션을 구현하며, 이번 PR이 이를 완성하는 형태로 코드 레벨에서 직접 연관된다.
  • imflint/Flint-Android#153: CollectionDetailScreen.ktCollectionDetailRoute/CollectionDetailScreen 콜백 시그니처를 같은 파일에서 확장하므로 병합 충돌 가능성이 있는 코드 레벨 연관 PR이다.
  • imflint/Flint-Android#104: CollectionDetailRoute(...) 공개 API 시그니처를 수정하는 PR로, 이번 PR도 동일 함수에 navigateToCollectionReport 파라미터를 추가하므로 코드 레벨에서 연관된다.

Suggested reviewers

  • giovannijunseokim

🐇 깡충깡충 토끼가 신고 버튼을 눌렀네,
DTO에서 API까지 깔끔하게 연결했어요~ 🎉
사유 선택하고 제출하면 토스트가 뜨고,
savedStateHandle에 플래그 저장, 완벽해요!
신고 기능, 이제 진짜 완성이에요~ 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive PR 설명이 템플릿 구조를 따르지만 관련 이슈 번호, 스크린샷 링크, 리뷰어 피드백이 미완성 상태입니다. 관련 이슈 번호(#XXXX)를 명시하고 실제 스크린샷 링크를 추가하며, 리뷰어를 위한 주요 검토 포인트를 기입해 주세요.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목 'Flt 22 컬렉션 신고 UI 제작'은 컬렉션 신고 UI 기능 추가라는 주요 변경사항을 명확하게 설명합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch FLT-22-컬렉션-신고-UI-제작

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chanmi1125 chanmi1125 added the 📱 UI feat - 컴포넌트 조립, 화면 구현 label Jun 17, 2026

@jongwoo2003-sidewalk jongwoo2003-sidewalk left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

코드 리뷰 — 컬렉션 신고 UI 제작

전반적인 구조와 플로우는 기존 컨벤션을 잘 따르고 있습니다. 아래 몇 가지 사항을 확인해 주세요.


🔴 필수 수정

1. isLoading 상태가 UI에 연결되어 있지 않음

CollectionReportUiStateisLoading 필드가 있고 ViewModel에서 업데이트하지만, CollectionReportScreen으로 전달되지 않아 제출 버튼이 API 호출 중에도 활성화된 상태로 남습니다. 빠르게 두 번 탭하면 중복 요청이 발생할 수 있습니다.

// isEnabled 계산 시 isLoading도 반영해야 함
val isEnabled = !uiState.isLoading && when (selectedReportReason) { ... }

2. Repository가 DTO를 직접 받음

다른 메서드들과 달리 postCollectionReport는 도메인 모델 대신 DTO를 파라미터로 받고 있습니다. ViewModel에서 .toDto() 변환 후 Repository에 전달하고 있는데, 이 변환은 Repository 내부에서 이루어져야 합니다.

// 현재 (ViewModel에서 변환)
collectionRepository.postCollectionReport(collectionId, requestModel.toDto())

// 올바른 방향 (Repository에서 변환)
collectionRepository.postCollectionReport(collectionId, requestModel)
// Repository 내부에서 requestModel.toDto() 호출

🟡 권장 수정

3. 신고 사유 문자열이 여러 곳에 분산

ReportCheck.kt의 하드코딩된 한국어 문자열과 CollectionReportViewModelREASON_CODE_MAP 키가 동일한 문자열을 중복 사용합니다. 문자열 하나라도 수정되면 두 파일 모두 수정해야 합니다.

enum으로 통합하는 것을 권장합니다.

enum class ReportReason(val displayText: String, val code: String) {
    ABUSE("욕설·혐오 표현이 포함된 콘텐츠", "ABUSE"),
    OBSCENE("음란하거나 선정적인 콘텐츠", "OBSCENE"),
    SPAM("광고·홍보 또는 스팸성 콘텐츠", "SPAM"),
    COPYRIGHT("저작권을 침해한 콘텐츠", "COPYRIGHT"),
    OTHER("기타", "OTHER"),
}

4. 텍스트 필드 포커스 시 자동으로 "기타" 선택

다른 항목이 선택된 상태에서 텍스트 필드를 탭하면 선택이 "기타"로 바뀌는 동작이 의도한 것인지 확인 부탁드립니다. 일반적으로는 선택 항목이 입력 필드 포커스에 의해 바뀌지 않는 방식이 더 자연스럽습니다.


🔵 선택 사항

  • 클릭 영역: ReportCheckItem의 클릭 영역이 아이콘 48dp로만 한정되어 있어 텍스트를 탭해도 선택되지 않습니다. Row 전체를 클릭 가능하게 하면 UX가 개선됩니다.
  • 신고 실패 처리 TODO: 의도적으로 미구현인 경우 PR 설명의 미구현 체크리스트에 명시해 주세요.
  • reasons 타입: 항상 단일 아이템으로만 전송된다면 API 스펙과 맞추어 List<String> vs String 재검토를 고려해 보세요.
  • PR 템플릿: 이슈 번호와 스크린샷이 기본 템플릿 그대로 남아 있습니다.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
app/src/main/java/com/flint/domain/model/collection/CollectionReportModel.kt (1)

3-5: 🏗️ Heavy lift

신고 사유 계약을 도메인 타입으로 승격해 문자열 의존을 줄여주세요.

reasons: List<String>는 코드값 오타/변경을 컴파일 타임에 막지 못합니다. 현재는 코드값 정의가 프레젠테이션(ReportReason.code)에 있고 도메인은 raw string을 받아서, API 계약 변경 시 영향 추적이 어려워집니다. 도메인에 전용 reason 타입(예: enum/value class)을 두고 DTO 매퍼에서만 문자열로 변환하는 구조가 더 안전합니다.

🤖 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 `@app/src/main/java/com/flint/domain/model/collection/CollectionReportModel.kt`
around lines 3 - 5, The `reasons` field in CollectionReportRequestModel is using
`List<String>` which lacks type safety and allows any string value, making it
impossible to catch invalid reason codes at compile time and difficult to track
API contract changes. Create a dedicated domain type for report reasons (such as
an enum or value class) and replace `List<String>` with `List<YourReasonType>`
in the CollectionReportRequestModel. Handle the conversion from string values
(coming from the API/presentation layer) to the domain reason type only in the
DTO mapper layer, keeping the domain model decoupled from raw string
dependencies and ensuring compile-time validation of valid reason codes.
🤖 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
`@app/src/main/java/com/flint/presentation/collectiondetail/report/CollectionReportScreen.kt`:
- Around line 42-44: The ReportFailure side effect handler in the
CollectionReportScreen is empty with only a TODO comment, providing no user
feedback when report submission fails. Implement the ReportFailure case in the
side effect handling block to display a toast or dialog message to inform users
that the report submission has failed. Replace the empty TODO comment with
appropriate UI feedback mechanism (such as showToast or showDialog) that conveys
the failure to the user.

In
`@app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportCheck.kt`:
- Around line 72-80: The clickable area for the report reason selection is
currently restricted to only the Icon component because the noRippleClickable
modifier with the onCheckClick callback is applied to the Icon. To expand the
touch target and improve user experience, move the noRippleClickable(onClick =
onCheckClick) modifier from the Icon to the Row container. This will make the
entire row clickable, allowing users to select the option by clicking either the
icon or the text.

In
`@app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportTopAppBar.kt`:
- Around line 44-48: The Icon composable used for the cancel button in
ReportTopAppBar has contentDescription set to null, which prevents accessibility
tools like TalkBack from describing the button's action to users. Replace the
null value with an appropriate string resource that describes the cancel action
(such as a localized string like "Close" or "Cancel") so that screen reader
users can understand the button's purpose.

---

Nitpick comments:
In
`@app/src/main/java/com/flint/domain/model/collection/CollectionReportModel.kt`:
- Around line 3-5: The `reasons` field in CollectionReportRequestModel is using
`List<String>` which lacks type safety and allows any string value, making it
impossible to catch invalid reason codes at compile time and difficult to track
API contract changes. Create a dedicated domain type for report reasons (such as
an enum or value class) and replace `List<String>` with `List<YourReasonType>`
in the CollectionReportRequestModel. Handle the conversion from string values
(coming from the API/presentation layer) to the domain reason type only in the
DTO mapper layer, keeping the domain model decoupled from raw string
dependencies and ensuring compile-time validation of valid reason codes.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d4a2d6de-21be-4e7b-81f6-12617276aac7

📥 Commits

Reviewing files that changed from the base of the PR and between 6e79a23 and 3f6b3a3.

📒 Files selected for processing (17)
  • app/src/main/java/com/flint/data/api/CollectionApi.kt
  • app/src/main/java/com/flint/data/dto/collection/request/CollectionReportRequestDto.kt
  • app/src/main/java/com/flint/domain/mapper/collection/CollectionReportMapper.kt
  • app/src/main/java/com/flint/domain/model/collection/CollectionReportModel.kt
  • app/src/main/java/com/flint/domain/repository/CollectionRepository.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/CollectionDetailScreen.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/navigation/CollectionDetailNavigation.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/CollectionReportScreen.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/CollectionReportUiState.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/CollectionReportViewModel.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/ReportReason.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportBottomSection.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportCheck.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/component/ReportTopAppBar.kt
  • app/src/main/java/com/flint/presentation/collectiondetail/report/navigation/CollectionReportNavigation.kt
  • app/src/main/java/com/flint/presentation/main/MainNavHost.kt
  • app/src/main/java/com/flint/presentation/main/MainNavigator.kt

@kimjw2003 kimjw2003 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

짱이다~

@chanmi1125 chanmi1125 merged commit 6073087 into develop Jun 18, 2026
2 checks passed
@chanmi1125 chanmi1125 deleted the FLT-22-컬렉션-신고-UI-제작 branch June 18, 2026 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔖 API feat - API 연동 🧩 Component feat - 공통 컴포넌트 작업 Feat ✨ 신규 기능을 추가하거나 기존 기능의 동작, 정책을 변경 📱 UI feat - 컴포넌트 조립, 화면 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants