Skip to content

Conversation

@ImHyungsuk
Copy link
Contributor

@ImHyungsuk ImHyungsuk commented Sep 26, 2025

📌 PR 요약

🌱 작업한 내용

  • 프로필 수정화면 구성
  • navigation 연결
  • 아직 완료버튼 구현 안됨

🌱 PR 포인트

  • 상태관리 아직 안됩니다..
  • 브랜치 따로 못팠어서 저번 이슈에 올렸습니다.

📸 스크린샷

|스크린샷|

mypage_profile_nav.webm

📮 관련 이슈

Summary by CodeRabbit

  • 신기능

    • 애니메이션과 아이콘 회전을 포함한 기본 드롭다운 UI 추가
    • 마이페이지용 페르소나 드롭다운 도입
    • 프로필 화면에 “나의 솔플 스타일” 선택 기능 추가
    • 메인에서 마이페이지/프로필로 이동 액션 및 내비게이션 그래프 연동
  • 스타일

    • 하향 화살표 아이콘 에셋 추가
  • 기타

    • “나의 솔플 스타일” 문자열 리소스 추가

@ImHyungsuk ImHyungsuk requested a review from a team September 26, 2025 05:46
@ImHyungsuk ImHyungsuk self-assigned this Sep 26, 2025
@ImHyungsuk ImHyungsuk added the 형석 🐧🍀 그날 인류는 떠올렸다 . 진격의 형석서서서석 label Sep 26, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 26, 2025

Walkthrough

새 드롭다운 UI(DesignSystem) 추가, 마이페이지(Persona 드롭다운/모델) 및 프로필 화면 갱신, 메인/마이페이지/프로필 내비게이션 경로와 헬퍼 추가, 상태/사이드이펙트 확장, 문자열 리소스 추가. 마이페이지에서 프로필로, 프로필에서 마이페이지로의 이동 훅이 MainScreen과 각 NavGraph에 연동됨.

Changes

Cohort / File(s) Change Summary
Design System DropDown
core/designsystem/.../component/dropdown/SolplyBasicDropDown.kt, core/designsystem/src/main/res/drawable/ic_arrow_down.xml
기본 드롭다운 컴포저블과 화살표 벡터 리소스 추가. 토글 아이콘 회전, AnimatedVisibility로 콘텐츠 슬라이드 인/아웃.
Main Navigation Wiring
feature/main/src/main/java/com/teamsolply/solply/main/MainNavigator.kt, feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt
navigateToMypage, navigateToProfile 헬퍼 및 훅 추가. MainScreen에서 mypage/profile NavGraph 간 상호 네비게이션 옵션 연결.
Mypage Contract & Model
feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt, feature/mypage/src/main/java/com/teamsolply/solply/mypage/model/DropDownPersonaItem.kt
상태에 nickname 필드 추가, 사이드이펙트 구체화(NavigateToBack/Profile/Mypage). Persona 드롭다운 아이템 데이터 클래스 추가.
Mypage UI Screens
feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt, feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt
마이페이지에 프로필 편집 클릭 콜백 추가. 프로필 화면에 완료 버튼 콜백 및 Persona 드롭다운 적용, Route 컴포저블 추가.
Navigation Graphs
feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt, feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt
Mypage NavGraph에 navigateToProfile 인자 추가. Profile 라우트/내비게이션 및 navigateProfile 확장 함수 신설.
Mypage Dropdown Component
feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt
Persona용 드롭다운 컴포저블 추가. 선택 상태/아이템 클릭 처리 및 기본 드롭다운 컴포넌트 활용.
Resources
feature/mypage/src/main/res/values/strings.xml
profile_solply_style 문자열 리소스 추가.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 사용자
  participant Main as MainScreen
  participant Nav as MainNavigator
  participant MyG as mypageNavGraph
  participant ProG as profileNavGraph
  participant MP as MypageScreen
  participant PR as ProfileScreen

  User->>Main: 앱 실행/탭 전환
  Main->>MyG: mypageNavGraph 등록(navigateToProfile)
  Main->>ProG: profileNavGraph 등록(navigateToMypage)

  User->>MP: 프로필 편집 클릭
  MP->>MyG: navigateToProfile 호출
  MyG->>Nav: navigator.navigateToProfile(navOptions)
  Nav->>ProG: navigate(Profile)

  Note over PR: 프로필 화면 표시

  User->>PR: 완료/뒤로 등 액션
  PR->>ProG: navigateToMypage 호출
  ProG->>Nav: navigator.navigateToMypage(navOptions)
  Nav->>MyG: navigate(Mypage)
Loading
sequenceDiagram
  autonumber
  actor User as 사용자
  participant UI as SolplyPersonaDropDown
  participant DS as SolplyBasicDropDown

  User->>DS: 헤더 클릭(아이콘)
  DS-->>UI: isDropped 토글 요청(onClickDropIcon)
  DS->>DS: AnimatedVisibility(열림/닫힘)

  alt 열림
    DS->>UI: 콘텐츠 슬롯 렌더
    loop 각 아이템(선택 제외)
      User->>UI: 아이템 클릭
      UI-->>Caller: onClickItem(index)
    end
  else 닫힘
    DS-->>User: 헤더만 표시
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

ui🎃

Suggested reviewers

  • leeseokchan00
  • nagaeng
  • 88guri

Poem

귀가 쫑긋, 드롭다운 톡!
프로필로 폴짝, 다시 마이페이지로 훅—
화살표는 살짝 돌아 인사하고,
퍼소나 골라 딱 맞게 꾸며요.
오늘도 코드밭 달리는 토끼,
경로는 깨끗, 클릭은 경쾌! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning 변경사항은 프로필 수정 화면과 내비게이션 로직 구현에 집중되어 있어 탑바와 프로필 이미지, 세부 기능 리스트를 포함한 마이페이지 첫 화면 UI 구현이라는 이슈 #132의 요구사항을 충족하지 않습니다. 이 PR이 이슈 #132의 요구사항을 만족하도록 탑바, 프로필 이미지, 세부 기능 리스트를 포함한 마이페이지 첫 화면 UI를 구현하거나, 프로필 수정 전용 PR로 분리하고 링크된 이슈를 업데이트해야 합니다.
Out of Scope Changes Check ⚠️ Warning 해당 PR에는 디자인 시스템의 드롭다운 컴포넌트 추가, 메인 화면 내비게이션 확장, 프로필 수정 화면과 관련된 전체 흐름 및 리소스 추가 등 이슈 #132의 마이페이지 리스트 UI 구현 범위를 벗어난 변경사항이 포함되어 있습니다. 마이페이지 리스트 UI 구현에 집중하고 드롭다운 컴포넌트나 프로필 수정 화면과 같은 범위 밖 변경사항은 별도의 PR로 분리하여 관련 이슈에 맞게 처리해 주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed 제목은 프로필 수정 UI 구현이라는 핵심 변경사항을 명확하게 요약하고 있으며 파일 목록이나 모호한 표현 없이 간결합니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#132-mypage-list-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.

Copy link

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

Caution

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

⚠️ Outside diff range comments (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt (1)

133-136: 완료 버튼이 네비게이션을 호출하지 않습니다.

ProfileRoute에서 navigateToMypage를 넘겨주지만, 실제 버튼의 onClick이 비어 있어 사용자가 완료를 눌러도 아무 동작이 없습니다. 최소한 넘겨준 콜백을 호출하도록 연결해야 합니다.

         SolplyBasicButton(
             text = "완료",
-            onClick = {},
+            onClick = onCompleteButtonClick,
             modifier = Modifier.padding(vertical = 24.dp, horizontal = 16.dp)
         )
🧹 Nitpick comments (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt (1)

15-19: NavOptions 파라미터에 기본값을 두어 API 사용성을 높여주세요.

기존 navigateMypage() 류와 달리 NavOptions를 항상 만들어 전달해야 해 ergonomics가 떨어집니다. null 기본값을 허용하고 내부에서 그대로 위임하도록 하면 호출부 부담이 줄어듭니다.

-fun NavController.navigateProfile(
-    navOptions: NavOptions
-) {
-    navigate(Profile, navOptions)
+fun NavController.navigateProfile(
+    navOptions: NavOptions? = null
+) {
+    navigate(Profile, navOptions)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be00269 and 5548e2a.

📒 Files selected for processing (12)
  • core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/dropdown/SolplyBasicDropDown.kt (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_arrow_down.xml (1 hunks)
  • feature/main/src/main/java/com/teamsolply/solply/main/MainNavigator.kt (2 hunks)
  • feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt (2 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt (1 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt (3 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt (1 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/model/DropDownPersonaItem.kt (1 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt (1 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt (4 hunks)
  • feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt (1 hunks)
  • feature/mypage/src/main/res/values/strings.xml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt (1)
core/designsystem/src/main/java/com/teamsolply/solply/designsystem/theme/Theme.kt (1)
  • SolplyTheme (46-53)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt (1)
  • ProfileRoute (36-48)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt (1)
  • MypageRoute (33-45)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt (1)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt (1)
  • SolplyPersonaDropDown (27-74)
🪛 detekt (1.23.8)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt

[warning] 14-16: The class or object MypageIntent is empty.

(detekt.empty-blocks.EmptyClassBlock)

🔇 Additional comments (6)
feature/mypage/src/main/java/com/teamsolply/solply/mypage/model/DropDownPersonaItem.kt (1)

3-5: 단순한 페르소나 항목 모델 추가 확인했습니다.
구조가 명확하고 이후 컴포넌트 연동에 문제 없어 보입니다.

feature/mypage/src/main/res/values/strings.xml (1)

6-6: 신규 문자열 리소스 추가 좋아요.
프로필 화면 문구와 일관성이 맞춰졌습니다.

core/designsystem/src/main/res/drawable/ic_arrow_down.xml (1)

1-13: 벡터 아이콘 정의 문제없습니다.
드롭다운 토글에 필요한 스타일과 스트로크값이 적절합니다.

feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt (1)

339-354: 마이페이지 ↔ 프로필 네비게이션 연결 확인했습니다.
navOptions 구성과 popUpTo 설정이 기대한 스택 정리에 부합합니다.

feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt (1)

20-33: 탐색 훅 전달 로직 명확합니다.
새로운 navigateToProfile 파라미터가 정상적으로 라우트에 전파됩니다.

feature/main/src/main/java/com/teamsolply/solply/main/MainNavigator.kt (1)

141-155: 네비게이터 보조 메서드 추가 확인했습니다.
탭 전환 외 개별 화면 호출 경로가 넓어져 재사용성이 좋아졌습니다.

Comment on lines +73 to +88
Icon(
painter = painterResource(R.drawable.ic_arrow_down),
contentDescription = "",
modifier = Modifier
.padding(end = 20.dp, top = 14.dp, bottom = 14.dp)
.height(24.dp)
.width(24.dp)
.scale(
scaleX = 1f,
scaleY = if (isDropped) -1f else 1f
)
.customClickable(
rippleEnabled = false,
onClick = onClickDropIcon
)
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

드롭다운 토글 아이콘에 접근성 라벨이 없습니다.
아이콘에 contentDescription=""로 설정된 상태에서 클릭 동작을 부여하면 스크린리더가 “레이블 없는 버튼”으로 인식해 조작 의도를 전달하지 못합니다. 최소한 기본 라벨을 읽어 주도록 설정해 주세요.

             Icon(
                 painter = painterResource(R.drawable.ic_arrow_down),
-                contentDescription = "",
+                contentDescription = defaultLabel,
                 modifier = Modifier
                     .padding(end = 20.dp, top = 14.dp, bottom = 14.dp)
                     .height(24.dp)
                     .width(24.dp)

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +39 to +44
defaultLabel = if (isSelected) dropDownContents.get(selectedIndex).label else placeholder,
onClickDropIcon = onClickDropIcon,
isDropped = isDropped,
modifier = modifier
) {
dropDownContents.forEachIndexed { index, item ->
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

선택 인덱스 검증 없이 get을 호출하면 크래시가 납니다.

selectedIndex가 리스트 범위를 벗어난 상태(예: 서버 갱신으로 리스트가 짧아진 경우)에서 isSelected가 true면 get이 바로 IndexOutOfBoundsException을 던집니다. 안전하게 getOrNull을 사용해 플레이스홀더로 대체하는 방식을 권장합니다.

-        defaultLabel = if (isSelected) dropDownContents.get(selectedIndex).label else placeholder,
+        defaultLabel = if (isSelected) {
+            dropDownContents.getOrNull(selectedIndex)?.label ?: placeholder
+        } else {
+            placeholder
+        },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
defaultLabel = if (isSelected) dropDownContents.get(selectedIndex).label else placeholder,
onClickDropIcon = onClickDropIcon,
isDropped = isDropped,
modifier = modifier
) {
dropDownContents.forEachIndexed { index, item ->
defaultLabel = if (isSelected) {
dropDownContents.getOrNull(selectedIndex)?.label ?: placeholder
} else {
placeholder
},
onClickDropIcon = onClickDropIcon,
isDropped = isDropped,
modifier = modifier
) {
dropDownContents.forEachIndexed { index, item ->
🤖 Prompt for AI Agents
In
feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt
around lines 39–44, calling dropDownContents.get(selectedIndex) without
validating selectedIndex can throw IndexOutOfBoundsException when the list has
shrunk; replace the unsafe get with a safe lookup and fallback to the
placeholder (e.g. use dropDownContents.getOrNull(selectedIndex)?.label ?:
placeholder) and/or ensure isSelected is only true when selectedIndex is within
bounds so the defaultLabel resolves safely to the selected item's label or the
placeholder.

Comment on lines +14 to +16
sealed interface MypageIntent : UiIntent {

sealed interface MypageSideEffect : SideEffect
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

detekt 경고의 원인이 된 빈 인터페이스 본문 제거 필요

sealed interface MypageIntent : UiIntent {} 형태로 바뀌면서 detekt.empty-blocks.EmptyClassBlock 경고가 발생하고, 파이프라인에서 실패할 가능성이 높습니다. 아직 구현할 멤버가 없다면 기존처럼 본문 없이 선언하거나 TODO를 추가해 주세요.

-sealed interface MypageIntent : UiIntent {
-
-}
+sealed interface MypageIntent : UiIntent

As per static analysis hints

🧰 Tools
🪛 detekt (1.23.8)

[warning] 14-16: The class or object MypageIntent is empty.

(detekt.empty-blocks.EmptyClassBlock)

🤖 Prompt for AI Agents
In feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt
around lines 14-16, the sealed interface is declared with an empty block "sealed
interface MypageIntent : UiIntent { }" which triggers
detekt.empty-blocks.EmptyClassBlock; remove the empty braces so it reads "sealed
interface MypageIntent : UiIntent" or, if you intend to add members later,
replace the empty block with a single TODO comment (e.g. "// TODO: add intents")
to satisfy static analysis.

Comment on lines +91 to 97
modifier = Modifier
.padding(top = 12.dp)
.customClickable(
rippleEnabled = false,
onClick = onProfileEditClick
)
) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

프로필 수정 탭 영역이 Material 최소 터치 타깃(48dp)을 만족하지 않습니다.

Row가 fillMaxWidth() 없이 텍스트 크기만큼만 확장되어 터치 영역이 매우 좁습니다. 접근성 측면에서 최소 48dp 정사각형 이상을 보장해야 하므로 가로폭과 패딩을 넓혀 주세요.

-        Row(
-            modifier = Modifier
-                .padding(top = 12.dp)
-                .customClickable(
-                    rippleEnabled = false,
-                    onClick = onProfileEditClick
-                )
-        ) {
+        Row(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(top = 12.dp)
+                .customClickable(
+                    rippleEnabled = false,
+                    onClick = onProfileEditClick
+                )
+                .padding(horizontal = 20.dp, vertical = 12.dp),
+            verticalAlignment = Alignment.CenterVertically
+        ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
modifier = Modifier
.padding(top = 12.dp)
.customClickable(
rippleEnabled = false,
onClick = onProfileEditClick
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 12.dp)
.customClickable(
rippleEnabled = false,
onClick = onProfileEditClick
)
.padding(horizontal = 20.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
// ... existing content ...
}
🤖 Prompt for AI Agents
In feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt
around lines 91–97, the profile-edit Row only sizes to its text and its touch
target is smaller than the Material minimum (48dp); change the Modifier to
expand the tappable area by adding fillMaxWidth() and increasing horizontal
padding, and enforce a minimum height (e.g., heightIn(min = 48.dp) or
sizeIn(minHeight = 48.dp)) so the customClickable covers a 48dp-high touch
target across the full width; ensure the Modifier order applies
fillMaxWidth()/padding()/heightIn() before customClickable so the whole area is
clickable.

Copy link
Contributor

@88guri 88guri left a comment

Choose a reason for hiding this comment

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

형석빠 수고하셨습니다

@ImHyungsuk ImHyungsuk merged commit 6d25245 into develop Sep 26, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

형석 🐧🍀 그날 인류는 떠올렸다 . 진격의 형석서서서석

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 마이페이지 목록 UI 구현

3 participants