Skip to content

🔀(64) :: 검색 기능을 구현 및 파일구조 변경 등 리펙토링을 했습니다.#65

Merged
kimjeakwan merged 106 commits intodevelopfrom
feature/64-admin-PostSerchScreen
Mar 8, 2025
Merged

🔀(64) :: 검색 기능을 구현 및 파일구조 변경 등 리펙토링을 했습니다.#65
kimjeakwan merged 106 commits intodevelopfrom
feature/64-admin-PostSerchScreen

Conversation

@kimjeakwan
Copy link
Collaborator

@kimjeakwan kimjeakwan commented Mar 7, 2025

💡 개요

검색 기능, 파일구조 변경,코드 컨벤션에 맞게 변경, Doma Navbar를 구현했습니다,

📃 작업내용

검색 기능을 구현하기 위한 PostDemeritSearchScreen 를 구현하고,
권한 병경을 위해 AdminAPI 에 권한변경을 추가했습니다. 선배님들이 코드리뷰해주신 파일구조 변경 및 네이밍을 리펙토링 했습니다. DomaNavbar 를 위한 combinnavgation 및 combinview 를 구현했습니다

🔀 변경사항

Admin API 권한변경 API 추가, AutrityRequest 추가, ChangeAuthorityUseCase 추가, CombinationViewNavgation 추가, DoMaCombinatinView 추가, DOmaSearchTextField 추가, GetStudentSearchUseCase 추가 LocalDatasource 에
ROle 추가, PostDemeirComponent 추가 , 예외처리를 위한 SearchEmptyText 추가
MainScreen에 scrollState 를 상태호이스팅

🙋‍♂️ 질문사항

  • 개선할 점, 오타, 코드에 이산한 부분이 있다면 Comment 달아주세요.

🍴 사용방법

🎸 기타

Summary by CodeRabbit

  • 신규 기능

    • 새로운 검색 및 학생 벌점 관리 화면과 인터페이스가 추가되어, 사용자가 학생 정보를 쉽게 조회하고 관리할 수 있게 되었습니다.
    • 내비게이션 바와 조합 뷰 등 주요 UI 요소가 업데이트되어 앱 전반의 인터랙션 및 디자인이 개선되었습니다.
  • 리팩토링 및 유지 보수

    • 사용자 권한 관리 및 인증 관련 기능이 강화되었으며, 토큰 갱신 프로세스 안정성이 향상되었습니다.
    • 전반적인 코드 구조 정리와 디자인 리소스 업데이트로 성능과 일관성이 개선되었습니다.

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: 13

🔭 Outside diff range comments (3)
presentation/src/main/java/view/mypage/navigation/MyPageNavigation.kt (1)

1-11: ⚠️ Potential issue

NavGraphBuilder 확장 함수가 누락되었습니다.

파일에 NavGraphBuilder의 확장 함수가 누락되어 있습니다. AI 요약에 따르면 이전 버전의 파일에는 NavGraphBuilder.MyScreen() 함수가 있었으나 현재 버전에는 포함되어 있지 않습니다. 화면을 정의하는 이 함수가 없으면 내비게이션 기능이 제대로 작동하지 않을 것입니다.

다음과 같이 MyScreen 함수를 추가하는 것을 권장합니다:

import androidx.compose.runtime.Composable
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import view.mypage.MyPageScreen

fun NavGraphBuilder.MyScreen(
    navigationBack: () -> Unit,
    onErrorToast: (throwable: Throwable?, message: Int?) -> Unit
) {
    composable(route = MyPage_route) {
        MyPageScreen(
            navigationBack = navigationBack,
            onErrorToast = onErrorToast
        )
    }
}
presentation/src/main/java/viewModel/admin/AdminViewModel.kt (2)

1-136: ⚠️ Potential issue

getStudentSearch 메소드 누락

AdminRepository에서 getUsersName이 getStudentSearch로 변경되었는데, 이 ViewModel에서는 해당 메소드가 구현되지 않았습니다. 검색 기능 구현을 위해 getStudentSearch 메소드를 추가해야 합니다.

다음과 같이 getStudentSearch 메소드를 추가하는 것을 권장합니다:

+    internal fun getStudentSearch(name: String) = viewModelScope.launch {
+        getAdminUsersUseCase.getStudentSearch(name)
+            .asResult()
+            .collectLatest { result ->
+                when (result) {
+                    is until.Result.Success -> {
+                        _getUserNameUiState.value = GetUserNameUiState.Success(result.data)
+                    }
+
+                    is until.Result.Loading -> {
+                        _getUserNameUiState.value = GetUserNameUiState.Loading
+                    }
+
+                    is until.Result.Error -> {
+                        _getUserNameUiState.value = GetUserNameUiState.Fail
+                    }
+                }
+            }
+    }

40-44: 💡 Verification agent

🧩 Analysis chain

미사용 상태 확인 필요

getUsersName 메소드가 제거되었지만, 관련 상태 필드인 _getUserNameUiState와 getUserNameUiState는 여전히 유지되고 있습니다. 더 이상 사용되지 않는다면 제거하는 것이 좋습니다.


🏁 Script executed:

#!/bin/bash
# getUserNameUiState 상태가 다른 곳에서 참조되는지 확인
rg "getUserNameUiState" --type kotlin

Length of output: 354


중요: 미사용 상태 필드 제거가 필요합니다

  • 현재 presentation/src/main/java/viewModel/admin/AdminViewModel.kt 파일 내에서 _getUserNameUiStategetUserNameUiState는 선언만 되어 있으며, 다른 곳에서 참조되는 흔적이 없습니다.
  • getUsersName 메소드가 제거된 상태에서 사용되지 않는 상태 필드라면, 불필요한 코드로 판단되어 제거하는 것이 좋겠습니다.
  • 만약 추후에 사용 용도가 명확해진다면, 해당 상태 필드의 유지 이유를 주석으로 명시하는 것도 고려해 주세요.
🧹 Nitpick comments (68)
buildSrc/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab (1)

1-3: 카운터 값 변경 의도 확인 요청

해당 파일에서 기존에 "5"로 설정된 값이 "3"으로 변경되었습니다. 이 변경이 캐시 또는 관련 빌드 설정과 연관되어 의도된 것인지 확인 부탁드립니다. 변경 배경 및 의도를 명확히 하기 위해 주석을 추가하는 것을 고려해보세요.

presentation/src/main/java/view/main/component/SearchEmptyText.kt (4)

19-20: 들여쓰기 수정이 필요합니다.

람다 매개변수의 들여쓰기가 일관되지 않습니다. 가독성을 위해 다음과 같이 수정하는 것이 좋습니다.

-    DoMaAndroidTheme {
-            colors, typography ->
+    DoMaAndroidTheme { colors, typography ->

26-26: Spacer 사용에 대한 고려가 필요합니다.

Column 내에서 width 모디파이어를 사용한 Spacer는 의도한 대로 작동하지 않을 수 있습니다. Column은 세로 방향 레이아웃이므로 공간을 주려면 height를 사용하는 것이 더 적절합니다.

-            Spacer(modifier = Modifier.width(4.dp))
+            Spacer(modifier = Modifier.height(4.dp))

27-32: 텍스트 스타일이 잘 적용되어 있습니다만, 공백 수정이 필요합니다.

텍스트 스타일과 색상이 적절히 적용되어 있습니다. 다만, text 속성에 불필요한 공백이 있습니다.

-                text ="없는 이름이에요!",
+                text = "없는 이름이에요!",

16-37: 문서화 및 UI 개선 제안

이 컴포넌트의 목적과 사용법을 설명하는 KDoc 주석을 추가하는 것이 좋습니다. 또한 사용자 경험 향상을 위해 텍스트 외에 아이콘이나 일러스트레이션을 추가하는 것을 고려해보세요.

+/**
+ * 검색 결과가 없을 때 표시되는 텍스트 컴포넌트입니다.
+ * 빈 결과 상태를 사용자에게 시각적으로 알립니다.
+ */
 @Composable
 internal fun SearchEmptyText() {
presentation/src/main/java/view/theme/color/ColorTheme.kt (3)

9-9: 속성 이름의 오타를 수정해주세요.

DARKGARY라는 이름에 오타가 있습니다. 올바른 스펠링은 DARKGRAY입니다 ('R'이 누락됨).

- abstract val DARKGARY: Color
+ abstract val DARKGRAY: Color

5-16: 색상 이름의 대소문자 표기법을 통일해주세요.

색상 속성 이름의 대소문자 표기가 일관되지 않습니다. 일부는 전부 대문자(MAIN, WHITE, GRAY), 일부는 첫 글자만 대문자(Black, Gold, Broze), 일부는 소문자(silver)로 되어 있습니다. 모든 색상 상수는 동일한 대소문자 규칙을 따라야 합니다.

모든 색상 상수를 UPPERCASE_WITH_UNDERSCORES 형식으로 통일하는 것을 권장합니다:

abstract class ColorTheme {
    abstract val MAIN: Color
-   abstract val Black: Color
+   abstract val BLACK: Color
    abstract val WHITE: Color
    abstract val DARKGARY: Color

    abstract val GRAY: Color
    abstract val LIGHTGRAY: Color
-   abstract val Gold: Color
-   abstract val silver: Color
-   abstract val Broze: Color
+   abstract val GOLD: Color
+   abstract val SILVER: Color
+   abstract val BRONZE: Color


    abstract val SYSTEM: Color

-   abstract val CardShadow: Color
-   abstract val StatusShadow: Color
+   abstract val CARD_SHADOW: Color
+   abstract val STATUS_SHADOW: Color
}

15-15: 속성 이름의 오타를 수정해주세요.

Broze라는 이름에 오타가 있습니다. 올바른 스펠링은 Bronze입니다 ('n'이 누락됨).

- abstract val Broze: Color
+ abstract val Bronze: Color
presentation/src/main/java/view/theme/color/DoMaColor.kt (4)

7-7: 속성 이름의 오타를 수정해주세요.

DARKGARY라는 이름에 오타가 있습니다. 올바른 스펠링은 DARKGRAY입니다 ('R'이 누락됨). ColorTheme 클래스에서도 동일한 수정이 필요합니다.

- override val DARKGARY = Color(0xFFBEBEBE)
+ override val DARKGRAY = Color(0xFFBEBEBE)

16-16: 속성 이름의 오타를 수정해주세요.

Broze라는 이름에 오타가 있습니다. 올바른 스펠링은 Bronze입니다 ('n'이 누락됨). ColorTheme 클래스에서도 동일한 수정이 필요합니다.

- override val Broze = Color(0xFFF7A080)
+ override val Bronze = Color(0xFFF7A080)

5-22: 색상 이름의 대소문자 표기법을 통일해주세요.

색상 속성 이름의 대소문자 표기가 일관되지 않습니다. 일부는 전부 대문자(MAIN, WHITE, GRAY), 일부는 첫 글자만 대문자(Black, Gold, Broze), 일부는 소문자(silver)로 되어 있습니다. 모든 색상 상수는 동일한 대소문자 규칙을 따라야 합니다.

모든 색상 상수를 UPPERCASE_WITH_UNDERSCORES 형식으로 통일하는 것을 권장합니다:

object DoMaColor : ColorTheme(){
    override val MAIN = Color(0xFF252525)
    override val DARKGARY = Color(0xFFBEBEBE)
-   override val Black = Color(0xFF000000)
+   override val BLACK = Color(0xFF000000)
    override val WHITE = Color(0xFFFFFFFF)


    override val LIGHTGRAY = Color(0xFF555555)
    override val GRAY = Color(0xFF9AD54A)
-   override val Gold = Color(0xFFFFD651)
-   override val silver = Color(0xFFBEBEBE)
-   override val Broze = Color(0xFFF7A080)
+   override val GOLD = Color(0xFFFFD651)
+   override val SILVER = Color(0xFFBEBEBE)
+   override val BRONZE = Color(0xFFF7A080)

    override val SYSTEM = Color(0xFF14C38E) // 시스템 색상 (강조 색으로 설정)

-   override val CardShadow = Color(0xFF1A1A1A) // 카드 그림자 색상
-   override val StatusShadow = Color(0xFF141414) //
+   override val CARD_SHADOW = Color(0xFF1A1A1A) // 카드 그림자 색상
+   override val STATUS_SHADOW = Color(0xFF141414) //


}

11-11: 불필요한 빈 줄을 제거해주세요.

11행의 빈 줄은 불필요해 보입니다. 코드의 가독성을 위해 불필요한 빈 줄은 제거하는 것이 좋습니다.

presentation/src/main/java/view/mypage/navigation/MyPageNavigation.kt (1)

6-6: 상수명에 오타가 있습니다.

MyPage_loute에 오타가 있습니다. 올바른 이름은 MyPage_route여야 합니다. 이러한 오타는 내비게이션 경로를 사용할 때 혼란을 줄 수 있습니다.

-const val MyPage_loute = "Mypage_loute"
+const val MyPage_route = "Mypage_route"
presentation/src/main/java/view/mypage/component/MyPageEmptyText.kt (1)

16-36: Composable 함수 구현이 깔끔합니다.

텍스트를 중앙에 배치하고 적절한 스타일링을 적용한 점이 좋습니다. 사용자에게 빈 상태에 대한 피드백을 제공하는 것은 UX 측면에서 중요합니다.

다만, 텍스트 메시지를 하드코딩하는 대신 문자열 리소스를 사용하는 것을 고려해 보세요. 이는 다국어 지원과 유지보수성을 향상시킵니다.

-            Text(
-                text ="조회에 실패했습니다.",
-                style = typography.bodySmall,
-                fontWeight = FontWeight.SemiBold,
-                color = colors.CardShadow
-            )
+            Text(
+                text = stringResource(id = R.string.lookup_failed),
+                style = typography.bodySmall,
+                fontWeight = FontWeight.SemiBold,
+                color = colors.CardShadow
+            )

stringResource를 사용하려면 import androidx.compose.ui.res.stringResource를 추가하고, strings.xml에 lookup_failed 리소스를 정의해야 합니다.

presentation/src/main/java/view/mypage/component/MyClean.kt (2)

71-95: 레이아웃 구조 개선 및 스타일 수정

Column에서 Row로 변경하여 이름과 인사말을 한 줄에 배치한 것은 더 나은 UI 디자인을 위한 좋은 개선입니다. 텍스트 스타일과 크기를 조정하여 가독성을 높인 점도 좋습니다.

그러나 AnnotatedString을 사용하는 부분에서 개선할 점이 있습니다. 현재 코드는 사용자 이름과 '님' 접미사를 하나의 문자열로 결합한 후 전체에 스타일을 적용하고 있습니다. 이름과 접미사에 다른 스타일을 적용하고 싶다면 다음과 같이 수정해 보세요:

-                    text = AnnotatedString.Builder("${data.name}님").apply {
-                        addStyle(
-                            style = SpanStyle(
-                                color = colors.GRAY, fontSize = 20.sp
-                            ),
-                            start = 0, end = data.name.length
-                        )
-                    }.toAnnotatedString(),
+                    text = buildAnnotatedString {
+                        append(data.name)
+                        withStyle(style = SpanStyle(color = colors.GRAY, fontSize = 20.sp)) {
+                            append("님")
+                        }
+                    },

이 방식을 사용하면 이름과 '님' 접미사에 다른 스타일을 더 직관적으로 적용할 수 있습니다.


227-243: 프리뷰 함수 추가는 좋은 개발 관행입니다.

Composable 함수를 위한 프리뷰 함수를 추가한 것은 개발 및 디자인 과정에서 UI를 빠르게 확인할 수 있어 좋은 방식입니다. 다양한 데이터 상황을 테스트하는 데 유용합니다.

그러나 더 완벽한 프리뷰를 위해 다양한 상황(예: 긴 이름, 빈 데이터 등)을 시뮬레이션하는 여러 프리뷰 함수를 추가하는 것을 고려해보세요.

presentation/src/main/java/view/mypage/component/DemeritList.kt (4)

75-75: 하드코딩된 문자열을 리소스로 관리하세요.

"벌점 리스트"와 같은 문자열은 하드코딩하지 말고 strings.xml 리소스 파일에서 관리하는 것이 좋습니다. 이렇게 하면 다국어 지원이 용이하고 텍스트 변경 시 코드 수정 없이 리소스만 수정하면 됩니다.

- text = "벌점 리스트",
+ text = stringResource(id = R.string.demerit_list),

107-107: 하드코딩된 색상 값을 테마에서 가져오는 값으로 대체하세요.

하드코딩된 색상 값(0xFFC1C1C1)은 테마 시스템을 통해 관리되는 것이 좋습니다. 이렇게 하면 다크 모드와 같은 테마 변경 시 자동으로 적절한 색상이 적용됩니다.

- color = Color(0xFFC1C1C1)
+ color = colors.GRAY // 또는 테마에서 제공하는 적절한 색상

98-98: horizontalAlignment 속성이 불필요할 수 있습니다.

Column 내의 Text 컴포넌트가 이미 Modifier.fillMaxWidth()를 사용하고 있어 horizontalAlignment 속성이 영향을 미치지 않을 수 있습니다. 불필요한 코드를 제거하는 것이 좋습니다.

- horizontalAlignment = Alignment.Start

117-117: 파일 끝에 불필요한 빈 줄이 있습니다.

파일 끝에 불필요한 빈 줄이 있습니다. 코드 일관성을 위해 제거하는 것이 좋습니다.

-
presentation/src/main/java/component/until/keyboardAsState.kt (1)

22-32: 성능 최적화를 고려해 볼 수 있습니다.

OnPreDrawListener는 UI가 그려질 때마다 호출되므로 성능에 영향을 줄 수 있습니다. 대안으로 WindowInsets.imeAnimationTarget과 함께 Modifier.onGloballyPositioned를 사용하거나, 키보드 상태 변경 시에만 이벤트를 받는 방식을 고려해 볼 수 있습니다.

@Composable
fun KeyboardAsState(): State<Boolean> {
    val windowInsets = WindowInsets.ime
    val context = LocalContext.current
    var isImeVisible by remember { mutableStateOf(false) }
    
    LaunchedEffect(context) {
        val windowInsetsController = WindowInsetsControllerCompat(
            context.findActivity().window, 
            context.findActivity().window.decorView
        )
        // 키보드 상태가 변경될 때만 호출되는 콜백
        windowInsetsController.addOnControllableInsetsChangedListener { controller, typeMask ->
            if (typeMask and WindowInsetsCompat.Type.ime() != 0) {
                isImeVisible = windowInsets.isVisible
            }
        }
    }
    
    return rememberUpdatedState(isImeVisible)
}

// Activity 찾는 확장 함수
fun Context.findActivity(): Activity {
    var context = this
    while (context is ContextWrapper) {
        if (context is Activity) return context
        context = context.baseContext
    }
    throw IllegalStateException("Activity를 찾을 수 없습니다")
}
presentation/src/main/res/drawable/notice.xml (1)

1-13: 알림 아이콘 벡터 드로어블 XML 검토
notice.xml 파일은 24dp 벡터 드로어블로, 투명한 채우기 색상과 회색 스트로크를 적절하게 사용하고 있습니다. 경로 데이터가 복잡하게 작성되어 있으므로, 추후 유지보수를 위해 각 주요 부분에 간단한 주석 추가를 고려해볼 수 있습니다.

presentation/src/main/res/drawable/notserach.xml (1)

1-20: 검색 관련 아이콘 파일명 및 구성 점검
notserach.xml 파일은 72dp 크기의 상세 벡터 드로어블로, 복잡한 android:pathData를 통해 정교한 그래픽을 표현하고 있습니다.
추가 검토 사항: 파일 이름에 "serach" 오타가 없는지 확인해 주시기 바랍니다(예: "notsearch.xml"으로 수정하는 것이 더 명확할 수 있음).

domain/src/main/java/emumtype/DomaNavBarItemType.kt (1)

1-7: 네비게이션 바 아이템 타입 열거형이 잘 정의되었습니다.

네비게이션 바 아이템 타입을 명확하게 정의하여 앱 내 이동을 체계적으로 관리할 수 있게 되었습니다.

다만, 일관성을 위해 모든 열거형 상수를 대문자로 통일하는 것이 좋을 것 같습니다:

enum class DomaNavBarItemType{
    HOME,
-   Notice,
+   NOTICE,
-   MY
+   MY
}
domain/src/main/java/emumtype/Authority.kt (1)

1-6: 권한 열거형이 잘 정의되었습니다.

사용자와 관리자 역할을 명확히 구분하는 열거형 정의가 좋습니다. 이는 권한 관리에 필수적인 요소입니다.

다만, 마지막 줄의 쉼표는 불필요합니다:

enum class Authority {
    ROLE_USER,
-   ROLE_MANAGER,
+   ROLE_MANAGER
}
domain/src/main/java/model/admin/request/AuthorityRequestModel.kt (1)

3-6: 데이터 모델 구조가 적절합니다.

권한 변경 요청을 위한 데이터 클래스가 명확하게 정의되어 있습니다. accountIdxauthority 속성이 적절히 포함되어 있습니다.

권한(authority) 필드에 입력 가능한 값에 대한 문서화를 추가하면 이 모델을 사용하는 개발자에게 더 도움이 될 것입니다.

domain/src/main/java/model/admin/response/AdminStudentListResponseModel.kt (2)

5-5: 불필요한 빈 줄이 있습니다.

불필요한 빈 줄을 제거하여 코드를 더 깔끔하게 정리할 수 있습니다.


6-11: 응답 모델 구조가 적절합니다.

학생 목록 응답을 위한 데이터 클래스가 필요한 속성들을 포함하고 있습니다. 각 속성의 타입도 적절하게 지정되어 있습니다.

모델에 대한 간단한 문서 주석을 추가하면 이 클래스의 용도와 관련 API를 더 명확하게 이해할 수 있을 것입니다.

/**
 * 관리자가 학생 목록을 조회할 때 사용되는 응답 모델
 *
 * @property name 학생 이름
 * @property penaltyPoint 벌점
 * @property roomNum 방 번호
 * @property userId 사용자 고유 식별자
 */
data class AdminStudentListResponseModel(
    val name: String,
    val penaltyPoint: Int,
    val roomNum: Int,
    val userId: UUID,
)
data/src/main/java/local/datasource/LocalDataSource.kt (1)

18-21: 권한 정보 관리를 위한 메서드가 추가되었습니다.

LocalDataSource 인터페이스에 추가된 두 메서드는 사용자의 권한 정보를 로컬에 저장하고 조회하는 기능을 담당합니다:

  • getAuthority(): 저장된 권한 정보를 Flow로 제공
  • setAuthority(): 권한 정보를 로컬에 저장

이 변경은 로그인 시 받은 권한 정보를 로컬에 캐싱하여 앱 전반에서 사용자 권한에 따른 기능 제어를 가능하게 합니다.

권한 정보 삭제 메서드(deleteAuthority())도 추가하는 것이 일관성 있는 패턴이 될 수 있습니다. 로그아웃 시 권한 정보도 함께 삭제하는 기능이 필요할 수 있습니다.

 fun getAuthority(): Flow<String>

 suspend fun setAuthority(authority: String)
 
+suspend fun deleteAuthority()
+
 fun getRefreshToken(): Flow<String>
domain/src/main/java/usecase/admin/ChangeAuthorityUseCase.kt (1)

7-13: 권한 변경 유스케이스 구현이 Clean Architecture 패턴을 잘 따르고 있습니다.

의존성 주입을 통해 AdminRepository를 받아 사용하는 패턴이 적절합니다. invoke 연산자 함수를 이용해 usecase를 직접 호출할 수 있게 한 부분도 좋습니다.

runCatching을 사용해 예외 처리를 하고 있지만, 실제로 발생한 예외를 처리하는 코드는 보이지 않습니다. 호출자에게 예외 정보를 전달하는 코드를 추가하는 것이 좋겠습니다.

 operator fun invoke(body: AuthorityRequestModel)= runCatching {
     adminRepository.changeAuthority(body = body)
+}.onFailure { error ->
+    // 로깅이나 특정 처리를 추가할 수 있습니다
+    throw error // 또는 적절한 예외 처리
 }
data/src/main/java/remote/dto/auth/response/GAuthLoginResponse.kt (1)

14-16: Authority 속성 추가 및 형식 개선 제안

Authority 속성이 잘 추가되었습니다. 다만, 15번 줄의 불필요한 빈 줄은 제거하는 것이 좋겠습니다.

    @Json(name = "Authority") val authority: Authority
-

)
presentation/src/main/java/view/main/component/PostDemeritComponent.kt (1)

1-56: 새로운 벌점 부여 컴포넌트가 추가되었습니다.

이 새로운 컴포넌트는 벌점 부여 기능에 대한 UI 요소를 제공합니다. 레이아웃은 잘 구성되어 있으며 DoMaAndroidTheme을 적용하여 일관된 스타일링을 유지하고 있습니다.

몇 가지 개선할 점:

  1. 아이콘 버튼의 내용이 단순히 DoMaIcon()으로 정의되어 있어 어떤 아이콘인지 명확하지 않습니다. 더 구체적인 아이콘 지정이 필요합니다.

  2. onDemeritStudentClick()을 직접 호출하기보다 onClick에 바로 함수 참조를 사용하는 것이 더 간결합니다.

IconButton(
-   onClick = { onDemeritStudentClick() },
+   onClick = onDemeritStudentClick,
    modifier = Modifier,
) {
-   DoMaIcon()
+   DoMaIcon(iconType = IconType.DEMERIT) // 또는 적절한 아이콘 유형
}
  1. Row 내부에 사용자 인터랙션 가이드나 툴팁을 추가하면 사용자 경험을 향상시킬 수 있습니다.
data/src/main/java/remote/dto/admin/request/AuthorityRequest.kt (1)

19-23: 불필요한 공백 라인을 제거해주세요.

toModel() 함수 내에 22-23번 라인 사이에 불필요한 빈 줄이 있습니다.

fun AuthorityRequest.toModel() = AuthorityRequestModel(
    accountIdx = accountIdx,
    authority = authority
-
)
presentation/src/main/java/view/main/component/StudentPatch.kt (1)

1-58: 적절한 코드 문서화가 필요합니다.

StudentPatch 컴포저블 함수에 대한 KDoc 문서화가 없습니다. 함수의 목적, 매개변수의 역할 및 사용 방법에 대한 설명을 추가하는 것이 좋습니다.

다음과 같이 문서화를 추가할 수 있습니다:

+/**
+ * 학생에게 벌점을 부여할 수 있는 UI 컴포넌트입니다.
+ *
+ * @param modifier 컴포넌트에 적용할 수 있는 수정자
+ * @param onStudentPatchClick 벌점 부여 버튼 클릭 시 실행할 콜백
+ */
@Composable
fun StudentPatch(
    modifier: Modifier = Modifier,
    onStudentPatchClick: () -> Unit,

    ) {
presentation/src/main/java/component/navigationbar/DomaNavBar.kt (1)

18-71: 내비게이션 바 구현이 잘 되었으나 수정이 필요한 부분이 있습니다.

전반적으로 Jetpack Compose 패턴을 잘 따르고 있지만, 몇 가지 개선할 점이 있습니다:

  1. 동일한 modifier 인스턴스가 여러 컴포저블에서 재사용되고 있습니다. 이로 인해 예상치 못한 동작이 발생할 수 있습니다.
  2. 일관성 없는 명명 규칙: DomaNavBarItemType.HOME은 대문자인 반면, 다른 항목들은 첫 글자만 대문자입니다.
  3. 내비게이션 아이템 간 간격이 명시되어 있지 않습니다.
  4. 접근성 기능(예: contentDescription)이 구현되어 있지 않습니다.

다음과 같이 수정하면 좋을 것 같습니다:

@Composable
fun DomaNavBar(
    modifier: Modifier = Modifier,
    currentDestination: DomaNavBarItemType,
    setCurrentDestination: (DomaNavBarItemType) -> Unit,
) {
    DoMaAndroidTheme { colors, typography ->
        Row(
            horizontalArrangement = Arrangement.SpaceBetween,
            modifier = modifier
                .fillMaxWidth()
                .background(colors.WHITE)
        ) {
            DomaNavBarItemType.values().forEach { item ->
                Column(
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally,
-                   modifier = modifier
+                   modifier = Modifier
                        .then(
                            if (currentDestination == item) {
                                Modifier
                            } else {
                                Modifier.clickablesingle(onClick = {setCurrentDestination(item)})
                            }
                        ),
                ) {
                    when (item) {
                        DomaNavBarItemType.Notice -> {
                            NoticeIcon(
                                isSelected = currentDestination == item,
-                               modifier = modifier,
+                               modifier = Modifier,
                            )
                        }

                        DomaNavBarItemType.HOME -> {
                            HomeIcon(
                                isSelected = currentDestination == item,
-                               modifier = modifier,
+                               modifier = Modifier,
                            )
                        }

                        DomaNavBarItemType.MY -> {
                            MyPageIcon(
                                isSelected = currentDestination == item,
-                               modifier = modifier,
+                               modifier = Modifier,
                            )
                        }
                    }

                }
            }
        }
    }
}
presentation/src/main/java/viewModel/homes/uistate/StudentListUiState.kt (1)

5-10: StudentListUiState 인터페이스가 잘 구현되었습니다.

일반적인 UI 상태(로딩, 비어있음, 성공, 실패)를 깔끔하게 처리하고 있습니다. 단, 작은 형식 오류가 있습니다:

sealed interface StudentListUiState {
-    object Loading :StudentListUiState
+    object Loading : StudentListUiState
    object Empty : StudentListUiState
    data class Success(val data: List<AdminUserListResponseModel>) : StudentListUiState
    data class Fail(val exception: Throwable) : StudentListUiState
}

콜론 뒤에 공백이 누락되어 있습니다. 일관성을 위해 추가하세요.

data/src/main/java/remote/dto/admin/request/AdminPenaltyRequest.kt (2)

10-16: AdminPenaltyRequest에 새로운 속성이 추가되었습니다.

accountIdx와 authority 필드가 추가되어 권한 관리 기능이 향상되었습니다. JSON 어노테이션도 적절히 적용되었습니다.

불필요한 공백 라인(15)을 제거하고 형식을 일관되게 유지하는 것이 좋겠습니다:

@JsonClass(generateAdapter = true)
data class AdminPenaltyRequest (
    @Json(name = "penaltyPoint") val penaltyPoint: Int,
    @Json(name = "because") val because: String,
    @Json(name = "accountIdx") val accountIdx: UUID,
    @Json(name = "authority") val authority: Authority
-

)

25-31: toModel() 함수에 새 속성이 추가되었습니다.

DTO를 Model로 변환하는 함수에 accountIdx와 authority 필드가 적절히 추가되었습니다.

불필요한 공백 라인(30-31)을 제거하고 형식을 일관되게 유지하는 것이 좋겠습니다:

fun AdminPenaltyRequest.toModel() = AdminPenaltyRequestModel(
    because = because,
    penaltyPoint = penaltyPoint,
    accountIdx = accountIdx,
    authority = authority
-

)
presentation/src/main/java/component/designsystem/DomaSearchTextField.kt (14)

30-30: 오타 확인 필요

component.modifier.SerchIcon 임포트에 오타가 있습니다. 'SerchIcon'에서 'a'가 빠져 'SearchIcon'이 되어야 합니다.

-import component.modifier.SerchIcon
+import component.modifier.SearchIcon

89-91: 하드코딩된 색상 값

Color(0xFF4C4C4C) 값이 하드코딩되어 있습니다. 이 값을 테마의 색상 상수로 추출하여 일관성을 유지하는 것이 좋습니다.

-.border(
-    width = 1.dp,
-    color = Color(0xFF4C4C4C),
-    shape = RoundedCornerShape(size = 8.dp)
-)
+.border(
+    width = 1.dp,
+    color = colors.DARKGARY,
+    shape = RoundedCornerShape(size = 8.dp)
+)

110-114: 일관된 네이밍 적용 필요

trailingIcon에서 SerchIcon을 사용하고 있습니다. 앞서 언급된 오타가 여기서도 반영됩니다.

-SerchIcon(
+SearchIcon(
    tint = colors.DARKGARY
)

34-35: 상수 이름 개선 필요

EMPTY 상수는 그 용도를 더 명확하게 나타내는 이름으로 변경하는 것이 좋습니다.

- const val EMPTY = ""
+ const val EMPTY_STRING = ""

82-83: 오타 수정 필요

DARKGARY는 오타로 보입니다. DARKGRAY가 올바른 표기입니다.

- color = colors.DARKGARY
+ color = colors.DARKGRAY

88-93: 하드코딩된 색상 값 대신 테마 색상 사용 권장

라인 90의 Color(0xFF4C4C4C)는 하드코딩된 값입니다. 테마 색상 시스템을 일관되게 사용하는 것이 좋습니다.

- color = Color(0xFF4C4C4C),
+ color = colors.DARKGRAY, // 또는 적절한 테마 색상

104-105: 오타 수정 필요

여기서도 DARKGARY 오타가 발견됩니다.

- focusedPlaceholderColor = colors.DARKGARY,
- unfocusedPlaceholderColor = colors.DARKGARY,
+ focusedPlaceholderColor = colors.DARKGRAY,
+ unfocusedPlaceholderColor = colors.DARKGRAY,

110-114: 검색 아이콘 접근성 개선 필요

검색 아이콘에 contentDescription이 없습니다. 접근성을 위해 추가하는 것이 좋습니다.

SerchIcon(
    tint = colors.DARKGARY
+   contentDescription = "검색"
)

111-113: 오타 수정 필요 및 컴포넌트 이름 검토

SerchIcon에 'a'가 빠져 있습니다. 올바른 철자는 SearchIcon입니다.

- SerchIcon(
-     tint = colors.DARKGARY
- )
+ SearchIcon(
+     tint = colors.DARKGRAY
+ )

122-129: 프리뷰 함수 개선

프리뷰 함수가 추가된 것은 좋습니다. 더 다양한 상태(예: 텍스트 입력됨, 포커스됨 등)를 보여주는 여러 프리뷰 함수를 추가하면 개발 과정에서 더 유용할 것입니다.


31-31: 오타가 있을 수 있습니다.

SerchIcon에 오타가 있는 것 같습니다. SearchIcon이 올바른 철자가 아닌지 확인해주세요.


83-83: 오타가 있을 수 있습니다.

DARKGARY에 오타가 있는 것 같습니다. DARKGRAY가 올바른 철자가 아닌지 확인해주세요.


90-92: 하드코딩된 색상 값을 테마로 이동하는 것이 좋습니다.

Color(0xFF4C4C4C)와 같은 하드코딩된 색상 값은 일반적으로 테마나 상수 파일에 배치하는 것이 좋습니다.

- color = Color(0xFF4C4C4C),
+ color = colors.borderColor, // 테마에 적절한 색상을 정의하세요

102-104: 포커스 상태에 따른 색상 구별을 고려해보세요.

포커스 및 비포커스 텍스트 색상이 모두 colors.MAIN으로 설정되어 있습니다. 일반적으로 이러한 상태 간에 시각적 구별이 있는 것이 좋습니다.

data/src/main/java/remote/datasource/admin/AdminDataSourceImpl.kt (1)

11-11: 대소문자 오타 발견

AdminStudentLIstResponse 임포트에 대소문자 오타가 있습니다. 'LIst'가 아닌 'List'가 되어야 합니다.

-import remote.dto.admin.response.AdminStudentLIstResponse
+import remote.dto.admin.response.AdminStudentListResponse
presentation/src/main/java/component/combinationvIew/CombinationViewNavigation.kt (1)

14-40: 매개변수가 많은 함수입니다.

NavGraphBuilder의 확장 함수에 매개변수가 10개나 있어 유지보수와 가독성이 저하될 수 있습니다. 객체나 데이터 클래스를 사용하여 관련 매개변수를 그룹화하는 것이 좋습니다.

매개변수를 그룹화하여 함수 시그니처를 개선하세요. 예를 들면:

data class NavigationCallbacks(
    val navigateToNotice: () -> Unit,
    val navigateToBack: () -> Unit,
    val navigateToMain: () -> Unit,
    val navigateToMyPage: () -> Unit,
    val navigateToLogin: () -> Unit
)

data class ActionCallbacks(
    val onDemeritStudentClick: () -> Unit,
    val onStudentPatchClick: () -> Unit,
    val onErrorToast: (throwable: Throwable?, message: Int?) -> Unit
)

fun NavGraphBuilder.combinationView(
    currentDestination: DomaNavBarItemType,
    setCurrentDestination: (DomaNavBarItemType) -> Unit,
    navigationCallbacks: NavigationCallbacks,
    actionCallbacks: ActionCallbacks
) {
    // 함수 구현...
}
presentation/src/main/java/view/main/screen/MainScreen.kt (6)

86-103: 매개변수가 많은 함수입니다.

MainScreen 함수에 매개변수가 많아 가독성과 유지보수성이 저하될 수 있습니다. 관련 매개변수를 그룹화하는 것이 좋습니다.

매개변수를 그룹화하여 함수 시그니처를 개선하세요. 예:

data class MainScreenCallbacks(
    val tokenRefreshCallBack: () -> Unit,
    val initTokenRefreshCallBack: () -> Unit,
    val myRankCallBack: () -> Unit,
    val rankListCallBack: () -> Unit,
    val onDemeritStudentClick: () -> Unit,
    val onStudentPatchClick: () -> Unit,
    val onErrorToast: (throwable: Throwable?, message: Int?) -> Unit,
    val navigateToBack: () -> Unit
)

data class MainScreenStates(
    val role: Authority,
    val isRefreshing: Boolean,
    val tokenRefreshUiState: TokenRefreshUiState,
    val homesUiState: HomesUiState,
    val homesMyRankUiState: HomesMyRankUiState
)

115-122: 시간 업데이트 로직에 대한 최적화 고려

무한 루프로 시간을 업데이트하는 방식은 일반적이지만, 배터리 소모와 성능에 영향을 줄 수 있습니다. 화면이 보이지 않을 때 업데이트를 중지하는 것이 좋습니다.

다음과 같이 리소스 사용을 최적화할 수 있습니다:

val lifecycleOwner = LocalLifecycleOwner.current
LaunchedEffect("Time") {
    lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        while (true) {
            delay(1_000L)
            currentTime = System.currentTimeMillis()
        }
    }
}

142-142: 하드코딩된 색상 값

배경색이 하드코딩되어 있습니다. 테마 시스템에서 정의된 색상을 사용하는 것이 좋습니다.

테마 색상을 사용하도록 변경하세요:

- .background(color = Color(0xFF1E1E1E)),
+ .background(color = colors.BACKGROUND),

이때 colors.BACKGROUND는 테마에 정의된 배경색 상수입니다. 이러한 상수가 없다면 테마에 추가해야 합니다.


183-185: 하드코딩된 색상 값

배경색이 하드코딩되어 있습니다. 테마 색상 시스템을 사용하는 것이 좋습니다.

테마 색상을 사용하도록 변경하세요:

- .background(color = Color(0xFF252525), shape = RoundedCornerShape(size = 10.dp)),
+ .background(color = colors.CARD_BACKGROUND, shape = RoundedCornerShape(size = 10.dp)),

208-214: 하드코딩된 텍스트 스타일과 색상

텍스트 스타일과 색상이 하드코딩되어 있어 테마 변경 시 일관성이 유지되지 않을 수 있습니다.

테마 스타일과 색상을 사용하도록 변경하세요:

- text = "순위", style = TextStyle(
-     fontSize = 14.sp,
-     fontWeight = FontWeight(600),
-     color = Color(0xFF555555),
- )
+ text = "순위",
+ style = typography.labelMedium,
+ color = colors.SECONDARY_TEXT

222-222: 하드코딩된 간격 값

Spacer의 너비가 하드코딩되어 있어 다양한 화면 크기에 대응하기 어렵습니다.

반응형 레이아웃을 위해 weight 또는 비율 기반 간격을 사용하세요:

- Spacer(modifier = Modifier.width(150.dp))
+ Spacer(modifier = Modifier.weight(1f))

또는 디자인 시스템에서 정의된 간격 상수를 사용하세요.

presentation/src/main/java/view/main/component/SearchList.kt (3)

33-90: SearchList Composable 구현

검색 결과를 표시하는 UI를 다양한 상태에 따라 적절하게 처리하고 있습니다. 검색 UI 상태와 학생 목록 UI 상태를 모두 고려하여 처리하는 구조가 잘 설계되었습니다.

다만, 하드코딩된 텍스트 문자열("로딩중", "검색 결과가 없습니다.")은 리소스 파일로 분리하는 것이 다국어 지원 및 유지보수에 더 좋습니다.

하드코딩된 문자열을 리소스 파일로 분리하는 것을 고려해보세요:

- Text(text = "로딩중")
+ Text(text = stringResource(id = R.string.loading))

- Text(text = "검색 결과가 없습니다.")
+ Text(text = stringResource(id = R.string.no_search_results))

93-144: SearchItem UI 구현

검색 결과 아이템의 UI를 구현하셨습니다. 하지만 하드코딩된 색상 값과 고정 너비 값(152.dp)이 있습니다. 이는 다양한 화면 크기에서 레이아웃 문제를 일으킬 수 있습니다.

다음과 같이 개선하는 것을 고려해보세요:

  1. 하드코딩된 색상을 테마 색상으로 변경:
- .background(color = Color(0xFF252525), shape = RoundedCornerShape(size = 10.dp))
+ .background(color = MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(size = 10.dp))

- color = Color(0xFF4C4C4C)
+ color = MaterialTheme.colorScheme.outline

- color = Color(0xFFFFFFFF)
+ color = MaterialTheme.colorScheme.onSurface
  1. 고정 너비 값 대신 가중치 또는 비율 사용:
- Spacer(modifier = Modifier.width(152.dp))
+ Spacer(modifier = Modifier.weight(1f))

146-170: SearchListComponent 구현

검색 목록을 표시하는 LazyColumn 구현이 잘 되어 있습니다. key를 사용하여 효율적인 재구성을 가능하게 한 점이 좋습니다.

다만, heightIn(max = 10_000.dp)는 매우 큰 값입니다. 이는 필요하지 않을 수 있으며, LazyColumn은 기본적으로 내용에 맞게 스크롤 가능합니다.

heightIn 제한을 제거하거나 더 합리적인 값으로 조정하는 것을 고려하세요:

- .heightIn(max = 10_000.dp)
+ // heightIn 제한 제거 또는
+ .heightIn(max = 600.dp) // 더 합리적인 값
presentation/src/main/java/component/combinationvIew/DoMaCombinationView.kt (1)

14-27: DomaCombinationView 함수 시그니처

DomaCombinationView 함수의 파라미터가 많습니다. 이렇게 많은 파라미터는 유지보수하기 어렵고, 함수 호출 시 실수할 가능성이 높습니다.

파라미터를 데이터 클래스로 그룹화하거나, 일관된 람다 그룹을 만드는 것을 고려해보세요:

data class NavigationCallbacks(
    val navigateToNotice: () -> Unit,
    val navigateToMain: () -> Unit,
    val navigateToMyPage: () -> Unit,
    val navigateToLogin: () -> Unit,
    val navigateToBack: () -> Unit,
    val onDemeritStudentClick: () -> Unit,
    val onStudentPatchClick: () -> Unit,
)

@Composable
fun DomaCombinationView(
    modifier: Modifier = Modifier,
    currentDestination: DomaNavBarItemType,
    setCurrentDestination: (DomaNavBarItemType) -> Unit,
    navigationCallbacks: NavigationCallbacks,
    onErrorToast: (throwable: Throwable?, message: Int?) -> Unit
)
presentation/src/main/java/view/main/screen/PostDemeritSearchScreen.kt (2)

62-105: UI 구조가 잘 설계되었습니다만, 개선할 부분이 있습니다.

검색 필드 구현과 키보드 포커스 관리가 잘 되어 있습니다. 하지만 검색 필드의 placeholder 텍스트 "방 호수, 이름 학년등을 검색해보세요"는 상수로 추출하거나 리소스 파일로 관리하는 것이 더 좋은 방법입니다.


106-134: 레이아웃 간격이 하드코딩되어 있습니다.

레이아웃에서 사용된 고정 간격 값들, 특히 150.dp와 같은 값은 다양한 디바이스 크기에서 제대로 표시되지 않을 수 있습니다. 상대적인 크기나 비율을 사용하거나 디자인 시스템에서 정의된 상수를 사용하는 것이 좋습니다.

presentation/src/main/java/viewModel/homes/HomesViewmodel.kt (2)

39-48: 주입 의존성이 많은 점에 대한 구조적 고려
ViewModel 생성자에 매우 많은 의존성을 직접 주입하면, 클래스가 지나치게 복잡해질 수 있습니다. Dagger/Hilt 등의 DI를 사용하는 상황이라면, UseCase가 서로 결합되는 공유 로직을 별도 모듈로 묶거나, ViewModel이 갖는 책임을 적절히 분리해볼 수 있습니다.


183-211: studentSearch에서 빈 결과 처리 로직의 중복 상태 설정
결과가 비어 있을 때 StudentSearchUiState.Loading을 일시적으로 다시 설정한 뒤 성공 상태로 전환하는 부분이 UI에서 잠깐 깜빡임(Flicker)을 일으킬 수 있습니다. Empty 상태를 별도로 두거나 바로 Success(emptyList())를 처리하는 형태로 개선을 고려해 보세요.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 512b3d3 and 0bd976f.

⛔ Files ignored due to path filters (3)
  • buildSrc/build/kotlin/compileKotlin/cacheable/last-build.bin is excluded by !**/*.bin
  • buildSrc/build/kotlin/compileKotlin/local-state/build-history.bin is excluded by !**/*.bin
  • buildSrc/build/libs/buildSrc.jar is excluded by !**/*.jar
📒 Files selected for processing (73)
  • .idea/other.xml (6 hunks)
  • app/src/main/java/DMNavHost.kt (0 hunks)
  • buildSrc/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab (1 hunks)
  • data/src/main/java/local/datasource/LocalDataSource.kt (1 hunks)
  • data/src/main/java/local/datasource/LocalDataSourceImpl.kt (1 hunks)
  • data/src/main/java/remote/api/auth/AdminAPI.kt (3 hunks)
  • data/src/main/java/remote/api/auth/NoticeAPI.kt (0 hunks)
  • data/src/main/java/remote/datasource/admin/AdminDataSource.kt (1 hunks)
  • data/src/main/java/remote/datasource/admin/AdminDataSourceImpl.kt (2 hunks)
  • data/src/main/java/remote/dto/admin/request/AdminCleanRequest.kt (1 hunks)
  • data/src/main/java/remote/dto/admin/request/AdminPenaltyRequest.kt (1 hunks)
  • data/src/main/java/remote/dto/admin/request/AuthorityRequest.kt (1 hunks)
  • data/src/main/java/remote/dto/admin/response/AdminPenaltyListResponse.kt (1 hunks)
  • data/src/main/java/remote/dto/admin/response/AdminStudentLIstResponse.kt (1 hunks)
  • data/src/main/java/remote/dto/admin/response/AdminUserListResponse.kt (1 hunks)
  • data/src/main/java/remote/dto/auth/response/GAuthLoginResponse.kt (1 hunks)
  • data/src/main/java/repoistory/AdminRepositoryImpl.kt (2 hunks)
  • data/src/main/java/repoistory/AuthRepositoryImpl.kt (1 hunks)
  • domain/src/main/java/emumtype/Authority.kt (1 hunks)
  • domain/src/main/java/emumtype/DomaNavBarItemType.kt (1 hunks)
  • domain/src/main/java/model/admin/request/AdminCleanRequestModel.kt (1 hunks)
  • domain/src/main/java/model/admin/request/AdminPenaltyRequestModel.kt (1 hunks)
  • domain/src/main/java/model/admin/request/AuthorityRequestModel.kt (1 hunks)
  • domain/src/main/java/model/admin/response/AdminStudentListResponseModel.kt (1 hunks)
  • domain/src/main/java/model/admin/response/AdminUserListResponseModel.kt (1 hunks)
  • domain/src/main/java/model/auth/response/GAuthLoginResponseModel.kt (1 hunks)
  • domain/src/main/java/reopoistory/AdminRepository.kt (1 hunks)
  • domain/src/main/java/reopoistory/AuthRepository.kt (1 hunks)
  • domain/src/main/java/usecase/admin/ChangeAuthorityUseCase.kt (1 hunks)
  • domain/src/main/java/usecase/admin/GetStudentSearchUseCase.kt (1 hunks)
  • presentation/src/main/java/component/combinationvIew/CombinationViewNavigation.kt (1 hunks)
  • presentation/src/main/java/component/combinationvIew/DoMaCombinationView.kt (1 hunks)
  • presentation/src/main/java/component/designsystem/DomaSearchTextField.kt (1 hunks)
  • presentation/src/main/java/component/modifier/DoMaIcon.kt (1 hunks)
  • presentation/src/main/java/component/navigationbar/DomaNavBar.kt (1 hunks)
  • presentation/src/main/java/component/until/keyboardAsState.kt (1 hunks)
  • presentation/src/main/java/until/Result.kt (1 hunks)
  • presentation/src/main/java/view/Mypage/component/DemeritList.kt (0 hunks)
  • presentation/src/main/java/view/Mypage/navigation/MyPageNavigation.kt (0 hunks)
  • presentation/src/main/java/view/main/Screen/MainScreen.kt (0 hunks)
  • presentation/src/main/java/view/main/component/MyPageButton.kt (1 hunks)
  • presentation/src/main/java/view/main/component/MyRankingComponent.kt (0 hunks)
  • presentation/src/main/java/view/main/component/PostDemeritComponent.kt (1 hunks)
  • presentation/src/main/java/view/main/component/Rankingcomponent.kt (0 hunks)
  • presentation/src/main/java/view/main/component/SearchEmptyText.kt (1 hunks)
  • presentation/src/main/java/view/main/component/SearchList.kt (1 hunks)
  • presentation/src/main/java/view/main/component/StudentPatch.kt (1 hunks)
  • presentation/src/main/java/view/main/navigation/MainNavigation.kt (1 hunks)
  • presentation/src/main/java/view/main/screen/MainScreen.kt (1 hunks)
  • presentation/src/main/java/view/main/screen/PostDemeritSearchScreen.kt (1 hunks)
  • presentation/src/main/java/view/mypage/component/DemeritList.kt (1 hunks)
  • presentation/src/main/java/view/mypage/component/MyClean.kt (5 hunks)
  • presentation/src/main/java/view/mypage/component/MyDemeritList.kt (3 hunks)
  • presentation/src/main/java/view/mypage/component/MyPageEmptyText.kt (1 hunks)
  • presentation/src/main/java/view/mypage/navigation/MyPageNavigation.kt (1 hunks)
  • presentation/src/main/java/view/mypage/screen/MyPage.kt (4 hunks)
  • presentation/src/main/java/view/notice/component/NoticeCard.kt (0 hunks)
  • presentation/src/main/java/view/notice/navgation/NoticeNavigation.kt (0 hunks)
  • presentation/src/main/java/view/notice/screen/NoticeScreen.kt (0 hunks)
  • presentation/src/main/java/view/theme/color/ColorTheme.kt (1 hunks)
  • presentation/src/main/java/view/theme/color/DoMaColor.kt (1 hunks)
  • presentation/src/main/java/viewModel/admin/AdminViewModel.kt (3 hunks)
  • presentation/src/main/java/viewModel/homes/HomesViewmodel.kt (4 hunks)
  • presentation/src/main/java/viewModel/homes/uistate/StudentListUiState.kt (1 hunks)
  • presentation/src/main/java/viewModel/homes/uistate/StudentSearchUiState.kt (1 hunks)
  • presentation/src/main/java/viewModel/login/uiState/TokenRefreshUiState.kt (1 hunks)
  • presentation/src/main/java/viewModel/users/UsersViewModel.kt (1 hunks)
  • presentation/src/main/res/drawable/home.xml (1 hunks)
  • presentation/src/main/res/drawable/left.xml (1 hunks)
  • presentation/src/main/res/drawable/mypage.xml (1 hunks)
  • presentation/src/main/res/drawable/notice.xml (1 hunks)
  • presentation/src/main/res/drawable/notserach.xml (1 hunks)
  • presentation/src/main/res/drawable/serach.xml (1 hunks)
💤 Files with no reviewable changes (10)
  • presentation/src/main/java/view/notice/screen/NoticeScreen.kt
  • presentation/src/main/java/view/main/component/Rankingcomponent.kt
  • presentation/src/main/java/view/notice/navgation/NoticeNavigation.kt
  • presentation/src/main/java/view/notice/component/NoticeCard.kt
  • presentation/src/main/java/view/main/Screen/MainScreen.kt
  • presentation/src/main/java/view/main/component/MyRankingComponent.kt
  • presentation/src/main/java/view/Mypage/navigation/MyPageNavigation.kt
  • data/src/main/java/remote/api/auth/NoticeAPI.kt
  • app/src/main/java/DMNavHost.kt
  • presentation/src/main/java/view/Mypage/component/DemeritList.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (129)
presentation/src/main/java/viewModel/users/UsersViewModel.kt (1)

3-4: 수정된 import 경로 확인
패키지 경로에서 첫 글자가 소문자인 “until”로 변경되어 올바른 네이밍 컨벤션을 따르게 되었습니다.

presentation/src/main/java/view/main/component/SearchEmptyText.kt (3)

1-15: 적절한 임포트와 패키지 구조가 잘 정의되어 있습니다.

Jetpack Compose UI 구성에 필요한 요소들을 잘 임포트하고 있습니다. 패키지 구조도 적절하게 view.main.component에 위치하여 재사용 가능한 컴포넌트임을 명확히 하고 있습니다.


16-17: 함수 선언이 명확합니다.

internal 접근 제한자를 사용하여 모듈 내에서만 접근 가능하도록 적절히 제한하였습니다.


21-25: 레이아웃 구조가 적절합니다.

Column을 사용하여 세로 방향으로 컨텐츠를 정렬하고, 가로 방향으로는 중앙 정렬을 적용한 것이 좋습니다. fillMaxWidth() 모디파이어로 전체 너비를 활용하는 것도 적절합니다.

presentation/src/main/java/view/main/component/MyPageButton.kt (3)

33-33: 코드 형식이 개선되었습니다.

이미지 컴포저블에서 불필요한 쉼표가 제거되어 코드 가독성이 향상되었습니다.


40-40: 코틀린 언어 기능을 활용한 코드 간소화가 좋습니다.

MyPageButton() {} 에서 MyPageButton {} 으로 변경되었습니다. 코틀린에서 마지막 매개변수가 람다일 경우 괄호 밖으로 람다를 이동할 수 있고, 다른 매개변수가 없을 경우 괄호를 완전히 생략할 수 있습니다. 이러한 Trailing Lambda 문법을 활용해 코드가 더 간결해졌습니다.


1-41:

Details

✅ Verification successful

불필요한 import 제거 작업이 필요합니다.

AI 요약에 따르면 여러 레이아웃 관련 컴포넌트의 import 문이 제거되었다고 하지만, 실제 코드에서는 여전히 사용되지 않는 import가 남아있는 것으로 보입니다. 특히 Box를 제외하고 다른 레이아웃 컴포넌트(Arrangement, Column, Row, height, width 등)에 대한 import가 있다면 제거하는 것이 좋을 것 같습니다.


🏁 Script executed:

#!/bin/bash
# 현재 파일에서 사용되지 않는 import 확인
grep -n "^import " presentation/src/main/java/view/main/component/MyPageButton.kt | while read line; do
  import=$(echo $line | sed 's/.*import \(.*\)/\1/')
  # Box, clickable, fillMaxWidth, padding, Image, Composable, Stable, Modifier, ContentScale, painterResource, Preview는 사용되므로 제외
  if ! echo "$import" | grep -q "Box\|clickable\|fillMaxWidth\|padding\|Image\|Composable\|Stable\|Modifier\|ContentScale\|painterResource\|Preview\|R"; then
    echo "Potentially unused import at line: $line"
  fi
done

Length of output: 4356


불필요한 import 검토 결과

  • 자동화 도구가 import androidx.compose.ui.unit.dp를 불필요한 것으로 표시했으나, 이는 실제로 padding(1.dp)에서 사용되므로 필요한 import입니다.
  • 나머지 import들은 모두 코드 내에서 사용되고 있어 제거할 불필요한 항목이 없습니다.
presentation/src/main/java/view/theme/color/DoMaColor.kt (1)

13-13: GRAY 색상 값이 실제 회색이 아닙니다.

GRAY 변수에 회색이 아닌 녹색 계열의 색상(0xFF9AD54A)이 할당되어 있습니다. 이는 변수명과 실제 색상이 일치하지 않아 혼란을 줄 수 있습니다. 실제 회색 색상을 사용하거나 변수명을 변경하는 것이 좋습니다.

- override val GRAY = Color(0xFF9AD54A)
+ override val GRAY = Color(0xFF808080) // 표준 회색 색상

또는 변수명을 변경하는 방법:

- override val GRAY = Color(0xFF9AD54A)
+ override val GREEN = Color(0xFF9AD54A) // 녹색 계열 색상
presentation/src/main/java/view/mypage/navigation/MyPageNavigation.kt (1)

1-11:

Details

❓ Verification inconclusive

검색 기능과의 연계성 확인 필요

PR의 목적은 검색 기능 구현이지만, 이 파일에는 검색 관련 코드가 없습니다. PR의 맥락에서 이 파일이 어떻게 검색 기능과 연계되는지 명확하지 않습니다. 또한 AI 요약에 따르면 이 파일은 이전에 삭제되었다고 되어 있는데, 현재 새 파일로 추가되고 있습니다. 이 파일이 여전히 필요한지, 아니면 리팩토링 과정에서 실수로 다시 추가된 것인지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# 이 파일이 다른 곳에서 참조되는지 확인
rg -i "MyPage_loute|navigationToMyPage" --type kotlin

Length of output: 378


검증 결과: 파일의 역할 및 검색 기능 연계성 불명확

  • 현재 presentation/src/main/java/view/mypage/navigation/MyPageNavigation.kt 파일은 내부에 정의된 MyPage_loute 상수와 navigationToMyPage() 함수만 포함하고 있으며, 다른 파일에서 참조되거나 검색 기능과 직접적인 연계성을 보여주지 않습니다.
  • AI 요약에 따르면 이전에 삭제되었다고 되어 있으나, 실제로는 새 파일로 추가되어 있어 리팩토링 과정에서 의도된 변경인지 여부가 불분명합니다.
  • 이 파일이 검색 기능 구현과 어떻게 연결되는지 명확하게 설명되거나, 혹은 불필요한 경우 삭제되어야 합니다.
presentation/src/main/java/view/mypage/screen/MyPage.kt (2)

35-35: ViewModel 인스턴스 생성 방식 개선됨

hiltViewModel()을 사용하여 ViewModel을 주입받는 방식으로 변경한 것은 좋은 개선입니다. 이렇게 하면 컴포넌트 간 의존성이 명확해지고 테스트가 용이해집니다.


55-55: ScrollState 파라미터화 좋은 접근입니다.

ScrollState를 함수 파라미터로 받도록 변경한 것은 컴포저블의 재사용성과 테스트 용이성을 높이는 좋은 패턴입니다. 특히 상위 컴포넌트에서 스크롤 상태를 제어해야 하는 경우 유용합니다.

presentation/src/main/java/view/mypage/component/MyDemeritList.kt (2)

54-56: 빈 상태 처리 개선됨

빈 상태일 때 MyPageEmptyText 컴포넌트를 사용하여 사용자에게 적절한 피드백을 제공하는 것은 좋은 UX 개선입니다.


105-109: 코드 포맷팅 개선됨

Column의 modifier를 여러 줄로 나누어 가독성을 높인 것은 좋은 변경입니다. 긴 modifier 체인을 여러 줄로 분리하면 코드를 더 쉽게 읽고 유지보수할 수 있습니다.

presentation/src/main/java/view/mypage/component/MyClean.kt (1)

54-56: 빈 상태 처리 개선됨

빈 상태일 때 MyPageEmptyText 컴포넌트를 사용하여 사용자에게 피드백을 제공하는 것은 좋은 UX 개선입니다. 일관된 오류 처리 방식으로 앱 전체의 사용자 경험을 향상시킵니다.

presentation/src/main/java/view/mypage/component/DemeritList.kt (1)

101-103:

Details

❓ Verification inconclusive

문자열 리소스 사용 방식을 검토하세요.

현재 stringResource를 사용하는 방식이 올바른지 확인이 필요합니다. R.string.stringResource라는 이름의 리소스 ID가 적절한지, 그리고 data.myBecausedata.penaltyPoint를 파라미터로 전달하는 것이 의도한 대로 동작하는지 확인해야 합니다.


🏁 Script executed:

#!/bin/bash
# strings.xml 파일에서 stringResource ID를 확인합니다
cat $(fd -t f "strings.xml" res/values/) | grep -A 3 "stringResource"

Length of output: 166


문자열 리소스 정의 및 사용 검증 필요
현재 코드에서 사용된 R.string.stringResource가 실제로 문자열 리소스 파일(strings.xml) 내에 올바르게 선언되어 있는지 확인이 필요합니다. 또한, 전달되는 인자(data.myBecause, data.penaltyPoint)가 해당 문자열 포맷의 자리표시자와 일치하는지 재검토해 주시기 바랍니다.

  • 프로젝트 내에 strings.xml 파일이 실제로 존재하는 경로(예: presentation/src/main/res/values/strings.xml)에서 stringResource 정의를 재확인해 주세요.
  • 문자열 포맷이 두 개의 인자를 받도록 정의되어 있는지 확인하시고, 리소스 ID가 의도한 이름과 일치하는지 점검해 주시기 바랍니다.
presentation/src/main/java/component/until/keyboardAsState.kt (3)

33-34: 구현이 잘 되어 있습니다.

전반적으로 키보드 상태를 감지하는 구현이 잘 되어 있습니다. 리스너 등록 및 해제가 적절히 처리되어 메모리 누수를 방지하고 있으며, rememberUpdatedState를 통해 최신 상태를 제공하는 점이 좋습니다.


1-1:

Details

✅ Verification successful

패키지 이름 검토가 필요합니다.

패키지 이름이 component.until로 되어 있는데, 'until'이 'util'의 오타는 아닌지 확인해주세요. 일반적으로 유틸리티 함수들은 'util' 패키지에 위치하는 것이 관례입니다.


🏁 Script executed:

#!/bin/bash
# 프로젝트 내에서 until과 util 패키지가 어떻게 사용되고 있는지 확인
echo "Searching for 'until' packages in the project:"
find . -type d -path "*/component/until" | sort
echo "Searching for 'util' packages in the project:"
find . -type d -path "*/component/util" | sort

Length of output: 359


패키지 네이밍 확인 완료

검증 결과, 리포지토리 내에 실제로 component/until 패키지가 존재하며, component/util 패키지는 확인되지 않았습니다.
따라서 현재 사용 중인 패키지 명이 의도한 것이면 그대로 유지해도 되지만, 일반적인 관례를 따른다면 유틸리티 함수들을 별도의 util 패키지로 관리하는 것도 고려해보시길 바랍니다.


17-18:

Details

❌ Incorrect review comment

Composable 함수 네이밍 컨벤션을 따르는 것이 좋습니다.

Jetpack Compose의 네이밍 컨벤션에 따르면, Composable 함수는 대문자로 시작하는 것이 권장됩니다. keyboardAsState 대신 KeyboardAsState로 변경을 고려해보세요.

-fun keyboardAsState(): State<Boolean> {
+fun KeyboardAsState(): State<Boolean> {

🌐 Web query:

Jetpack Compose 함수 네이밍 컨벤션

💡 Result:

Jetpack Compose 함수의 네이밍 컨벤션은 코드의 가독성과 일관성을 유지하기 위해 다음과 같은 규칙을 따릅니다.

1. Unit 반환 @composable 함수

  • PascalCase 사용
    UI 요소를 생성하는 모든 @Composable 함수는 명사형의 PascalCase로 작성합니다[1][4][7].
    예: FancyButton(), ProfileHeader()

  • 동사/형용사 사용 금지
    함수명이 동사(예: RenderButton())나 형용사(예: Fancy())로 시작해서는 안 됩니다[1][4].

올바른 예시

@Composable
fun UserProfileCard() { /* ... */ }  // 명사 + PascalCase

잘못된 예시

@Composable
fun drawButton() { /* ... */ }  // 동사 + 소문자 시작

2. 값 반환 @composable 함수

  • camelCase 사용
    Unit 이외의 값을 반환하는 함수는 Kotlin 코딩 컨벤션에 따라 camelCase로 작성합니다[1][3][7].
    예: defaultStyle(), rememberCoroutineScope()

  • remember 접두사 권장
    내부에서 remember를 사용해 객체를 관리하는 함수는 remember로 시작합니다[3][5].

    @Composable
    fun rememberViewModel(): MyViewModel { /* ... */ }

3. CompositionLocal 네이밍

  • "Local"을 접두사로 사용
    CompositionLocal 키는 값의 특성을 설명하는 명사 앞에 Local을 붙입니다[1][5][9].
    val LocalTheme = staticCompositionLocalOf<Theme>()  // 올바른 예
    val ThemeLocal = staticCompositionLocalOf<Theme>()  // 잘못된 예

4. 기타 규칙

  • Modifier 위치
    modifier 매개변수는 함수의 첫 번째 선택적 인자로 배치합니다[8].

    @Composable
    fun CustomButton(
        modifier: Modifier = Modifier,  // 첫 번째 선택적 인자
        onClick: () -> Unit
    ) { /* ... */ }
  • Preview 함수
    미리보기용 함수에는 Preview 접미사를 추가합니다[8].

    @Preview
    @Composable
    fun UserProfileCardPreview() { /* ... */ }

비교 테이블: 권장 vs 비권장 사례

유형 권장 예시 비권장 예시
UI 컴포저블 SettingsScreen() createSettingsUI()
값 반환 함수 calculateTextWidth() TextWidthCalculator()
CompositionLocal LocalDensity DensityLocal

이 규칙들은 Compose 컴파일러의 최적화와 팀 협업 효율성을 높이기 위해 설계되었습니다. 특히 명사형 PascalCase는 선언적 UI의 특성을 반영하며, remember 접두사는 객체의 수명 주기를 명확히 합니다[3][5][7].

Citations:


네이밍 컨벤션 검증 결과: keyboardAsState 이름이 올바릅니다.

해당 함수는 State<Boolean>을 반환하는 값 반환 @composable 함수에 해당합니다. 웹 검색 결과에 따르면, 값 반환 함수는 Kotlin 코딩 컨벤션에 따라 camelCase를 사용해야 하므로, 현재의 keyboardAsState 네이밍이 적절합니다. PascalCase는 UI 요소를 생성하여 Unit을 반환하는 함수에 권장되므로, 이 경우에는 변경하지 않는 것이 좋겠습니다.

Likely an incorrect or invalid review comment.

presentation/src/main/res/drawable/left.xml (1)

1-14: 아이콘 벡터 드로어블 정의 점검
새로 추가된 left.xml 파일은 벡터 드로어블을 통해 24dp 크기의 아이콘을 적절하게 표현하고 있습니다. xmlns, width, height, viewport 속성 등이 올바르게 지정되었으며, <path> 요소의 속성 (fillColor, strokeColor, strokeWidth, strokeLineCap, pathData) 도 디자인 가이드에 부합하는지 최종 확인하시기 바랍니다.

presentation/src/main/res/drawable/home.xml (1)

1-15: 홈 아이콘 벡터 드로어블 구성 적합성 확인
home.xml 파일은 24dp 크기 내에서 두 개의 <path> 요소를 사용하여 일관된 색상(#7F7F7F)으로 홈 아이콘을 구현하고 있습니다. 디자인 요구사항에 부합하며, XML 구조도 명확합니다.

presentation/src/main/res/drawable/mypage.xml (1)

1-15: 마이페이지 아이콘 XML 검토
mypage.xml 파일은 사용자 프로필과 관련된 아이콘을 위한 벡터 드로어블로, 24dp 크기와 적절한 stroke 속성(색상, 두께, 라운드 처리) 및 투명한 fillColor를 사용하여 깔끔하게 구현되어 있습니다.

domain/src/main/java/model/admin/response/AdminUserListResponseModel.kt (1)

10-10: AdminUserListResponseModel에 roomNum 속성이 잘 추가되었습니다.

사용자 목록 응답 모델에 방 번호 정보를 추가한 것은 기숙사 관리 시스템에 적합한 변경사항입니다. 이 정보는 검색 기능 구현에 유용할 것으로 보입니다.

domain/src/main/java/reopoistory/AuthRepository.kt (1)

18-18: 역할 조회 기능이 잘 추가되었습니다.

AuthRepository에 사용자 역할을 조회하는 메서드가 추가된 것은 권한 기반 기능 구현에 적합합니다. Flow를 반환하여 반응형으로 설계한 점이 좋습니다.

data/src/main/java/repoistory/AuthRepositoryImpl.kt (1)

22-24: 역할 조회 기능이 적절하게 구현되었습니다.

사용자 역할을 가져오는 getRole() 메서드가 localDataSource.getAuthority()를 호출하여 구현되어 있으며, 기존 코드 구조에 잘 통합되어 있습니다.

domain/src/main/java/model/auth/response/GAuthLoginResponseModel.kt (2)

3-4: Authority 타입 import가 추가되었습니다.

이는 새로 추가된 authority 필드에 필요한 import로, 로그인 응답 모델에 권한 정보를 포함하기 위한 준비입니다.


5-11:

Details

❓ Verification inconclusive

사용자 권한 정보 필드가 로그인 응답 모델에 추가되었습니다.

로그인 응답 모델에 authority 필드를 추가함으로써 인증 과정에서 사용자의 권한 정보를 함께 관리할 수 있게 되었습니다. 이는 권한 기반 기능 접근 제어에 필수적인 개선사항입니다.

다만, 이 변경으로 인해 기존에 이 모델을 사용하는 코드에서 호환성 문제가 발생할 수 있으니 관련 코드들도 함께 업데이트되었는지 확인해 보세요.


🏁 Script executed:

#!/bin/bash
# GAuthLoginResponseModel을 사용하는 코드 검색
rg "GAuthLoginResponseModel" --type kotlin

Length of output: 2616


새로운 'authority' 필드 추가 검증 완료 및 추가 확인 필요

GAuthLoginResponseModel에 사용자 권한 정보를 관리하기 위한 'authority' 필드가 추가되었습니다. 검색 결과, 이 모델이 여러 곳(예: AuthRepositoryImpl, HomesViewmodel, TokenRefreshUiState, AuthViewModel, remote/dto/auth/response/GAuthLoginResponse.kt, 도메인 및 유즈케이스 관련 파일 등)에서 사용되고 있음을 확인했습니다.

따라서 아래 사항들을 꼭 점검해 주세요:

  • 관련 DTO 변환 함수(예: GAuthLoginResponse.toLogin())가 새로운 'authority' 필드를 올바르게 매핑하고 있는지 검토
  • 해당 모델을 사용하는 리포지토리 및 뷰모델 등의 변경 사항에 따른 호환성 문제가 없는지 확인

전반적으로 개선사항은 긍정적이나, 다른 부분에서도 새 필드 처리 누락이 없는지 재검토하시길 바랍니다.

domain/src/main/java/usecase/admin/ChangeAuthorityUseCase.kt (1)

1-6: 권한 변경 유스케이스를 위한 기본 설정이 적절합니다.

필요한 패키지와 의존성 주입을 위한 import가 올바르게 설정되어 있습니다.

domain/src/main/java/model/admin/request/AdminPenaltyRequestModel.kt (2)

3-5: 필요한 타입 import가 추가되었습니다.

새로 추가된 필드인 accountIdx와 authority 타입을 위한 import가 적절히 추가되었습니다.


9-10:

Details

❓ Verification inconclusive

관리자 페널티 요청 모델에 계정 식별자와 권한 정보가 추가되었습니다.

페널티 요청 모델에 다음 필드가 추가되었습니다:

  • accountIdx: 페널티를 부여할 계정의 고유 식별자
  • authority: 계정의 권한 정보

이는 관리자 기능에서 특정 사용자에게 페널티를 부여할 때 필요한 정보를 명확하게 해줍니다.

페널티를 부여하는 데 authority 필드가 필요한 이유가 명확하지 않습니다. 페널티 부여 시 권한 변경이 함께 이루어지는 것인지, 아니면 권한 검증을 위한 것인지 코드 주석이나 문서화가 필요합니다.


🏁 Script executed:

#!/bin/bash
# AdminPenaltyRequestModel 사용 코드와 관련 API 검색
rg "AdminPenaltyRequestModel" --type kotlin -A 10
rg "penaltyPoint.*authority" --type kotlin

Length of output: 11396


[확인 필요] authority 필드의 역할에 대한 추가 문서화 요청

  • AdminPenaltyRequestModel (domain/src/main/java/model/admin/request/AdminPenaltyRequestModel.kt)에서 accountIdxauthority 필드가 새로 추가되었습니다.
  • 해당 모델은 DTO 변환 및 관련 UseCase(예: PostPenaltyUseCase)와 Repository 계층에서 사용되고 있음을 확인했습니다.
  • 다만, 현재 코드에서는 authority 필드가 페널티 부여 시 권한 변경을 위한 것인지, 아니면 단순 권한 검증을 위한 것인지 명확하게 드러나지 않습니다.
  • 관련 코드를 사용하는 여러 파일(예: AdminPenaltyRequest DTO, AdminRepository, AdminRepositoryImpl 등)에서도 이 점에 대한 별도 설명이나 주석이 부족합니다.

추후 혼란을 방지하기 위해 authority 필드의 의도와 사용 목적을 명확히 하는 코드 주석 또는 문서 업데이트를 부탁드립니다.

data/src/main/java/remote/dto/admin/response/AdminUserListResponse.kt (2)

9-15: roomNum 속성 추가 - 좋은 변경!

AdminUserListResponse 데이터 클래스에 roomNum 속성을 추가한 것은 사용자 정보에 방 번호를 포함시켜 검색 기능에 필요한 정보를 제공할 수 있게 해줍니다. 이는 PR 목표인 검색 기능 구현에 적절한 변경입니다.


18-24: toModel 함수에 roomNum 속성 추가 완료

모델 변환 함수에 roomNum 속성이 올바르게 추가되었습니다. 데이터 클래스와 모델 클래스 간의 일관성이 잘 유지되었습니다.

data/src/main/java/remote/dto/auth/response/GAuthLoginResponse.kt (2)

6-6: Authority 열거형 추가 및 임포트

Authority 열거형을 추가하고 임포트한 것은 사용자 권한 관리를 위한 좋은 접근법입니다. 열거형을 사용하면 타입 안전성이 높아집니다.


21-22: toLogin 함수에 authority 속성 적용 완료

모델 변환 함수에 authority 속성이 올바르게 추가되었습니다. 이로써 사용자 권한 정보가 모델 계층으로 잘 전달됩니다.

data/src/main/java/remote/dto/admin/response/AdminStudentLIstResponse.kt (1)

1-7: 임포트 및 패키지 선언 확인

필요한 모든 임포트가 올바르게 선언되었습니다.

domain/src/main/java/model/admin/request/AdminCleanRequestModel.kt (2)

3-5: 필요한 임포트 추가

Authority와 UUID 타입을 사용하기 위한 임포트가 올바르게 추가되었습니다.


6-11: 계정 ID와 권한 속성 추가

AdminCleanRequestModel에 accountIdx와 authority 속성을 추가한 것은 사용자 권한 관리와 검색 기능에 필요한 좋은 변경입니다. 이는 PR의 목표인 검색 기능 구현과 관련이 있으며, 사용자 식별과 권한 검증에 도움이 됩니다.

data/src/main/java/remote/dto/admin/request/AdminCleanRequest.kt (1)

5-7: 계정 식별자와 권한 정보가 추가되었습니다.

AdminCleanRequest 데이터 클래스에 accountIdxauthority 속성이 추가되었습니다. 이러한 변경은 다른 요청 모델(예: AdminPenaltyRequest)과의 일관성을 유지하고, 계정 권한 관리 기능을 통합하는 데 기여합니다.

data class AdminCleanRequest(
    @Json(name = "toDayClean") val toDayClean: String,
    @Json(name = "cleanPoint") val cleanPoint: Int,
+   @Json(name = "accountIdx") val accountIdx: UUID,
+   @Json(name = "authority") val authority: Authority,
)

이 변경사항은 API 통신 시 사용자 식별 및 권한 확인에 필요한 정보를 포함시켜 더 안전하고 명확한 요청을 가능하게 합니다.

Also applies to: 13-14, 20-21, 27-28

presentation/src/main/java/until/Result.kt (2)

1-1: 패키지 이름이 수정되었습니다.

패키지 이름이 Untill에서 until로 변경되었습니다. 이는 코드 스타일 가이드라인에 맞게 적절한 케이스 컨벤션을 적용한 것입니다.


8-9:

Details

❓ Verification inconclusive

타입 매개변수에서 'out' 한정자가 제거되었습니다.

Success 클래스의 타입 매개변수 T에서 out 한정자가 제거되었습니다:

- data class Success<out T>(val data: T) : Result<T>
+ data class Success<T>(val data: T) : Result<T>

주의: Result 인터페이스는 여전히 out T를 사용하고 있지만, Success 클래스에서는 제거되었습니다. 이는 타입 공변성(covariance)에 영향을 줄 수 있으며, 일부 타입 변환 관련 컴파일 오류를 발생시킬 가능성이 있습니다.

다음 패턴으로 코드베이스를 확인하여 이 변경으로 인한 영향을 평가해보세요:


🏁 Script executed:

#!/bin/bash
# Success 클래스를 사용하는 부분 찾기
rg "Success<" --type kotlin

Length of output: 123


타입 매개변수 'out' 제거 영향 재확인

검증 결과, Success 클래스 사용은 현재 presentation/src/main/java/until/Result.kt 파일 내에만 존재하는 것으로 확인되었습니다. 다만, Result 인터페이스는 여전히 out T를 사용하고 있으므로, Success 클래스에서 out 한정자를 제거한 변경이 타입 공변성에 영향을 줄 가능성이 있습니다. 이로 인해 특정 상황에서 타입 변환 관련 컴파일 오류가 발생할 수 있으니, 해당 변경 사항이 전반적인 타입 안정성에 부정적인 영향을 미치지 않는지 추가 확인해주시길 바랍니다.

  • 변경된 코드:
    - data class Success<out T>(val data: T) : Result<T>
    + data class Success<T>(val data: T) : Result<T>
data/src/main/java/remote/dto/admin/response/AdminPenaltyListResponse.kt (1)

9-9: JSON 필드 이름 오타가 수정되었습니다.

pointList 속성의 JSON 어노테이션이 수정되었습니다:

- @Json(name = "ponitList") val pointList: Int,
+ @Json(name = "pointList") val pointList: Int,

이 수정으로 JSON 직렬화/역직렬화 과정에서 필드와 속성이 올바르게 매핑됩니다. 이는 백엔드 API와의 통신에서 잠재적인 오류를 방지하는 중요한 수정입니다.

data/src/main/java/remote/dto/admin/request/AuthorityRequest.kt (2)

8-12: 데이터 클래스 구조가 적절합니다.

AuthorityRequest 데이터 클래스가 Moshi 직렬화를 위한 적절한 어노테이션을 포함하고 있습니다. accountIdx와 authority 필드 모두 JSON 매핑이 올바르게 설정되어 있습니다.


14-17: 모델 변환 로직이 잘 구현되었습니다.

AuthorityRequestModel을 DTO로 변환하는 확장 함수가 명확하게 구현되어 있습니다.

domain/src/main/java/usecase/admin/GetStudentSearchUseCase.kt (2)

8-10: 클래스 이름 변경이 적절합니다.

기존 GetUsersNameUseCase에서 GetStudentSearchUseCase로 변경되어 기능을 더 명확하게 표현하고 있습니다.


11-12: 메소드 파라미터 타입 변경과 기능 호출 변경이 일관성 있게 적용되었습니다.

파라미터가 nullable(String?)에서 non-nullable(String)로 변경되었고, 호출 메소드도 getUsersName에서 getStudentSearch로 일관되게 변경되었습니다. 이는 검색 기능의 목적에 맞게 적절히 개선된 부분입니다.

data/src/main/java/local/datasource/LocalDataSourceImpl.kt (3)

14-20: 권한 관련 키 추가가 적절합니다.

AUTHORITY 키가 다른 인증 관련 키들과 함께 AuthDataStoreKey companion object에 잘 추가되었습니다.


22-25: 권한 조회 메소드 구현이 적절합니다.

권한 정보를 조회하는 getAuthority() 메소드가 다른 조회 메소드들과 동일한 패턴으로 구현되어 있습니다. 권한이 없을 경우 빈 문자열을 반환하는 것도 적절합니다.


27-31: 권한 설정 메소드 구현이 적절합니다.

권한을 설정하는 setAuthority() 메소드가 다른 설정 메소드들과 동일한 패턴으로 구현되어 있습니다.

presentation/src/main/java/view/main/component/StudentPatch.kt (4)

22-27: 컴포저블 함수 시그니처가 적절합니다.

StudentPatch 컴포저블 함수의 매개변수가 적절하게 정의되어 있습니다. 기본 Modifier와 클릭 이벤트 콜백이 포함되어 있습니다.


28-37: Row 레이아웃 구성이 적절합니다.

DoMaAndroidTheme을 적용하고 Row 레이아웃을 사용하여 내용을 수평으로 배치하는 구성이 잘 되어 있습니다. 크기와 패딩, 정렬 설정이 적절합니다.


38-47: 텍스트 스타일 설정이 적절합니다.

"벌점 주기" 텍스트에 대한 스타일이 적절하게 지정되어 있습니다. 폰트 크기, 패밀리, 두께, 색상 및 정렬이 잘 구성되어 있습니다.


48-53:

Details

❓ Verification inconclusive

IconButton에서 DoMaIcon 파라미터가 누락되었습니다.

DoMaIcon()을 사용할 때 어떤 아이콘을 표시할지에 대한 파라미터가 지정되지 않았습니다. IconButton의 onClick 함수 내부에 onStudentPatchClick() 함수가 올바르게 호출되고 있지만, DoMaIcon에 아이콘 유형이나 추가 속성이 전달되지 않았습니다.


🏁 Script executed:

#!/bin/bash
# DoMaIcon 컴포넌트 정의를 확인
ast-grep --pattern "fun DoMaIcon" -A 20

Length of output: 41


검증 요청: DoMaIcon 컴포넌트 정의 재확인 필요

현재 IconButton 내부에서 호출되는 DoMaIcon()에 아이콘 종류를 지정하는 인자가 누락된 것으로 보입니다. 다만, 실행한 ast-grep 명령어에서는 DoMaIcon 함수 정의의 결과가 나오지 않아 해당 컴포넌트가 프로젝트 내 어디에서 정의되었는지 확인되지 않았습니다.

  • DoMaIcon 컴포넌트가 외부 라이브러리 또는 별도 파일에서 정의되어 있다면, 인자 전달이 필요한지 확인해 주세요.
  • 정의가 프로젝트 내에 존재한다면, 올바른 아이콘 식별자(예: icon parameter)를 전달하도록 수정이 필요합니다.
  • 해당 컴포넌트의 정의와 사용법을 수동으로 재검토하여, 의도한 인자 전달이 이뤄지고 있는지 확인해 주시기 바랍니다.
presentation/src/main/java/viewModel/login/uiState/TokenRefreshUiState.kt (1)

5-9: 토큰 갱신 UI 상태가 잘 구현되었습니다.

토큰 갱신 작업의 다양한 상태(로딩, 성공, 오류)를 명확하게 표현하고 있습니다. 코드가 깔끔하고 Kotlin의 sealed interface 기능을 적절히 활용하였습니다.

data/src/main/java/remote/dto/admin/request/AdminPenaltyRequest.kt (2)

5-7: 새로운 import가 추가되었습니다.

Authority 열거형과 UUID 타입이 추가되어 권한 관리 기능이 확장되었습니다.


18-23: toDto() 함수에 새 속성이 추가되었습니다.

Model을 DTO로 변환하는 함수에 accountIdx와 authority 필드가 적절히 추가되었습니다.

domain/src/main/java/reopoistory/AdminRepository.kt (9)

6-6: 새로운 요청 모델 추가 확인.

AuthorityRequestModel 임포트가 권한 변경 기능을 위해 추가되었습니다.


15-15:

Details

❓ Verification inconclusive

API 메소드 시그니처가 변경되었습니다.

getUsersName(name: String?) 메소드가 getStudentSearch(name: String)로 대체되었습니다. String? 에서 String으로 변경되어 이제 null 값이 허용되지 않으므로, 호출하는 쪽에서 이 변화에 맞게 조정이 필요합니다.


🏁 Script executed:

#!/bin/bash
# 이전 getUsersName 메소드를 호출하는 코드를 확인
rg "getUsersName\(" --type kotlin

Length of output: 35


API 메소드 시그니처 변경 – 호출부 추가 검증 요청

해당 커밋에서 기존의 getUsersName(name: String?) 메소드가 getStudentSearch(name: String)로 대체되었습니다. 이로 인해 파라미터 타입이 String?에서 String으로 변경되어, 호출하는 쪽에서도 null 값 전달이 불가능하도록 조정되어야 합니다.

  • 변경 사항 검증: AdminRepository.kt 파일에서 변경된 메소드 시그니처를 확인하였으며, rg "getUsersName(" --type kotlin 명령어로 호출부를 검색했을 때 결과가 나타나지 않아, 기존 호출부가 제거되었거나 수정된 것으로 보입니다.
  • 추가 검증 요청: 다만, 검색 결과가 낮은 품질의 추론에 기반된 것이므로, 프로젝트 내에서 여전히 getUsersName을 호출하는 부분이 없는지 수동으로 재검증해 주시기 바랍니다.

17-17:

Details

❓ Verification inconclusive

권한 변경 기능이 추가되었습니다.

새로운 changeAuthority 메소드가 추가되었습니다. 이 기능의 구현부가 모든 구현 클래스에 추가되었는지 확인해주세요.


🏁 Script executed:

#!/bin/bash
# AdminRepository 구현체에서 changeAuthority 구현 여부 확인
rg "class \w+Impl.*?implements AdminRepository" -A 30 --multiline | rg "override fun changeAuthority"

Length of output: 103


확인 필요: changeAuthority 오버라이드 구현 관련

현재 스크립트로 검색한 결과, AdminRepository를 구현하는 클래스에서 override fun changeAuthority가 발견되지 않았습니다.
이로 인해 추가 검증이 필요할 것 같습니다.

  • 모든 AdminRepository 구현 클래스(*Impl)에서 changeAuthority 메소드가 올바르게 오버라이드되어 구현되었는지 수동으로 확인해 주시기 바랍니다.
  • Kotlin에서는 클래스가 인터페이스를 구현할 때 implements가 아니라 :를 사용하므로, 아래와 같이 수정된 정규식으로 다시 한번 검증해 보시는 것이 좋겠습니다.

검증 결과에 따라, 해당 메소드가 모든 구현체에 추가되었다면 이 리뷰는 해결된 것으로 판단할 수 있으며, 그렇지 않으면 추가 구현이 필요합니다.


🏁 Script executed:

#!/bin/bash
# AdminRepository 구현체에서 changeAuthority 구현 여부 재검증 (Kotlin 문법 ':' 사용)
rg -t kotlin "class \w+Impl\s*:\s*AdminRepository" -A 50 --multiline | rg "override fun changeAuthority"

Length of output: 228


조치 필요: 모든 구현체에 changeAuthority 오버라이드 확인

자동화 스크립트를 통해 재검증한 결과, AdminRepository를 구현하는 클래스(예: *Impl)에서 override fun changeAuthority 구문이 발견되지 않았습니다. Kotlin에서는 인터페이스 구현 시 implements 대신 :를 사용하지만, 수정된 정규식으로도 기대한 결과가 출력되지 않았으므로 해당 메소드가 모든 구현 클래스에 올바르게 추가되었는지 수동 검증이 필요합니다.

  • 확인 대상: 모든 AdminRepository 구현 클래스 (예: *Impl)
  • 검증 포인트: changeAuthority 메소드 오버라이드 여부

6-6: 새로운 권한 관리 모델 임포트 추가

AuthorityRequestModel의 임포트가 추가되었습니다. 이는 권한 변경 기능을 위한 중요한 모델입니다.


15-15: 검색 기능 메서드 시그니처 개선

기존 getUsersName(name: String?) 메서드를 대체하여 널 허용 매개변수를 사용하지 않는 getStudentSearch(name: String)로 변경한 것은 좋은 접근 방식입니다. 이로써 널 처리에 대한 부담이 줄고 명확한 API를 제공합니다.


17-17: 권한 변경 기능 추가

새로운 권한 변경 기능이 추가되었습니다. Flow<Unit> 반환 타입은 작업 완료 신호만 필요한 경우에 적합합니다.


6-6: 적절한 임포트가 추가되었습니다.

권한 변경 기능을 위한 AuthorityRequestModel 임포트가 추가되었습니다.


15-15: 메소드 시그니처 개선이 이루어졌습니다.

이전 getUsersName(name: String?) 메소드가 getStudentSearch(name: String)로 변경되었습니다. 파라미터가 nullable에서 non-nullable로 변경되어 항상 유효한 이름이 제공되어야 함을 명확히 했습니다.


17-17: 새로운 기능이 추가되었습니다.

권한 변경 기능을 위한 changeAuthority 메소드가 적절히 추가되었습니다. Flow<Unit> 반환 타입은 데이터를 반환하지 않는 작업에 적합합니다.

presentation/src/main/java/viewModel/admin/AdminViewModel.kt (5)

3-3: 클래스명 변경 적용됨

Untill 클래스명이 until로 변경되었습니다. 소문자 시작은 Kotlin 코딩 컨벤션에 더 적합합니다.


52-62: 클래스명 참조 업데이트 완료

모든 Untill.Result 참조가 until.Result로 일관되게 변경되었습니다.


67-90: 코드 포맷팅 개선

postPenalty 메소드의 들여쓰기와 포맷팅이 개선되었습니다. 일관된 코딩 스타일로 코드 가독성이 향상되었습니다.


97-107: 클래스명 참조 업데이트 완료

getPenaltyList에서도 until.Result 참조로 일관되게 변경되었습니다.


114-135: 코드 포맷팅 개선

postClean 메소드의 들여쓰기와 파라미터 포맷팅이 개선되었습니다.

presentation/src/main/java/component/designsystem/DomaSearchTextField.kt (15)

36-52: 잘 설계된 API 구조

DomaSearchTextField 컴포넌트가 다양한 사용 사례를 지원하기 위한 풍부한 파라미터 세트를 가지고 있습니다. 기본값을 제공하여 사용 편의성도 높였습니다.


57-61: 효율적인 리소스 관리

DisposableEffect를 사용하여 컴포넌트 해제 시 포커스를 정리하고, LaunchedEffect를 사용하여 디바운스 기능을 효과적으로 구현했습니다.

Also applies to: 63-66


71-74: 입력 필터링 로직 검토 필요

현재 모든 공백을 필터링하고 있습니다. 이는 사용자가 검색할 때 단어 사이의 공백을 넣지 못하게 합니다. 이것이 의도적인 설계인지 확인해 주세요. 대부분의 검색에서는 공백을 허용합니다.

공백을 필터링하는 이유가 있는지, 혹은 이것이 의도적인 설계인지 확인하세요. 검색 결과에 영향을 줄 수 있습니다.


122-129: 미리보기 구현 좋음

미리보기 기능을 통해 컴포넌트를 시각적으로 테스트할 수 있어 개발 효율성이 향상됩니다.


37-52: 검색 필드 컴포넌트 매개변수 구성

잘 설계된 컴포넌트입니다. 다양한 매개변수와 기본값을 통해 유연하게 사용할 수 있습니다. 특히 debounceTime 매개변수는 검색 기능에서 불필요한 API 호출을 방지하는 좋은 접근 방식입니다.


63-66: 디바운스 처리 구현

LaunchedEffect와 delay를 사용한 디바운스 구현이 잘 되어 있습니다. 이는 사용자 입력 중에 불필요한 검색 요청을 줄이는 효율적인 방법입니다.


71-74: 모든 공백 문자 필터링 로직 검토 필요

현재 코드는 모든 공백 문자를 필터링하고 있습니다. 이는 일부 검색 시나리오에서는 적합하지 않을 수 있습니다. 검색어에 공백이 필요한 경우(예: "홍 길동")가 있을 수 있습니다.

- val filteredText = it.filterNot { text -> text.isWhitespace() }
+ val filteredText = it.trim() // 앞뒤 공백만 제거하고 단어 사이 공백은 유지

102-103: 텍스트 색상과 배경 색상 확인 필요

텍스트 색상과 배경 색상이 모두 MAIN으로 설정되어 있습니다. 이는 적절한 대비를 제공하지 않을 수 있으며 가독성 문제가 발생할 수 있습니다. 색상 대비를 확인하고 필요하면 조정해 주세요.


1-33: 컴포넌트 구조 및 임포트가 적절합니다.

패키지 구성과 필요한 Compose 및 유틸리티 의존성 임포트가 잘 정리되어 있습니다.


34-34: 상수 정의가 적절합니다.

빈 문자열을 위한 EMPTY 상수가 잘 정의되어 있습니다.


36-52: 매개변수 목록이 포괄적입니다.

합리적인 기본값을 가진 포괄적인 매개변수 목록이 잘 구성되어 있습니다.


57-61: 자원 관리가 적절합니다.

컴포넌트가 제거될 때 DisposableEffect를 사용하여 포커스를 정리하는 것은 좋은 자원 관리 방법입니다.


63-66: 디바운스 구현이 적절합니다.

LaunchedEffect를 사용한 디바운스 구현은 과도한 검색 작업을 방지하는 좋은 성능 최적화입니다.


72-73: 공백 필터링 로직을 검토해주세요.

현재 구현은 입력에서 모든 공백을 제거합니다. 이는 사용자가 공백이 포함된 구문을 검색하려는 경우에 의도하지 않은 동작일 수 있습니다.

// 현재 구현:
val filteredText = it.filterNot { text -> text.isWhitespace() }

// 대안 구현 (연속된 공백만 제거):
val filteredText = it.replace("\\s+".toRegex(), " ").trim()

122-129: 프리뷰 컴포저블이 적절합니다.

IDE에서 시각적 테스트를 위한 프리뷰 함수가 포함되어 있으며, 필요한 최소 매개변수로 간단한 예제를 제공합니다.

data/src/main/java/remote/datasource/admin/AdminDataSourceImpl.kt (3)

21-23: 학생 검색 기능 구현 완료

getStudentSearch 메소드가 적절히 구현되었습니다. 이제 null이 아닌 문자열 매개변수를 강제하여 API의 안정성이 향상되었습니다.


24-25: 권한 변경 기능 구현 완료

changeAuthority 메소드가 적절히 구현되었습니다. API 호출 시 performApiRequest를 사용하여 오류 처리와 응답 변환을 일관되게 처리합니다.


1-38:

Details

❓ Verification inconclusive

미사용 메소드 제거 확인 필요

getUsersName 메소드가 제거되었습니다만, 이 메소드를 사용하던 코드가 모두 업데이트되었는지 확인이 필요합니다.


🏁 Script executed:

#!/bin/bash
# getUsersName 메소드를 호출하는 코드를 확인
rg "getUsersName\(" --type kotlin

Length of output: 35


검증 요청: 미사용 메소드 제거 관련 수동 확인 필요

자동 검색 도구(rg "getUsersName\(" --type kotlin)로 확인한 결과, 코드베이스 내에서 getUsersName 호출 부분이 검색되지 않았습니다. 다만, 자동 검색 결과의 신뢰성이 완벽하지 않으므로 실제 사용처가 모두 반영되었는지 직접 수동으로 검증해 주시길 바랍니다.

  • 확인 파일: data/src/main/java/remote/datasource/admin/AdminDataSourceImpl.kt
  • 검증 항목: getUsersName 메소드가 제거되었고, 이 메소드를 호출하던 코드가 모두 업데이트되었는지 확인
presentation/src/main/java/viewModel/homes/uistate/StudentSearchUiState.kt (1)

5-11: 잘 구현된 상태 관리 인터페이스입니다!

검색 UI의 다양한 상태를 sealed interface로 명확하게 정의한 점이 좋습니다. Loading, Empty, QueryEmpty, Success, Error 상태를 통해 검색 결과의 모든 가능한 상태를 포괄적으로 처리할 수 있습니다. 특히 Success 상태에서 데이터 리스트를 포함하고, Error 상태에서 예외를 캡처하는 방식이 효과적입니다.

presentation/src/main/java/component/modifier/DoMaIcon.kt (3)

14-24: 적절하게 구현된 아이콘 컴포저블입니다.

이미지 리소스를 활용하여 간결하게 구현되었습니다.


37-48: 적절하게 구현된 아이콘 컴포저블입니다.

선택 상태에 따라 색상이 적절히 변경되도록 구현되었습니다.


49-60: 적절하게 구현된 아이콘 컴포저블입니다.

선택 상태에 따라 색상이 적절히 변경되도록 구현되었습니다.

presentation/src/main/java/component/combinationvIew/CombinationViewNavigation.kt (1)

8-12: 간결하게 구현된 네비게이션 확장 함수입니다.

NavController의 확장 함수를 사용하여 네비게이션 로직을 캡슐화한 것이 좋습니다.

presentation/src/main/java/view/main/screen/MainScreen.kt (3)

55-84: MainRoute 함수가 간결하게 구현되었습니다.

ViewModel의 상태를 수집하고 MainScreen에 전달하는 패턴이 적절합니다. Authority 열거형의 사용도 효과적입니다.


104-113: 초기화 및 오류 처리 로직이 적절합니다.

LaunchedEffect와 DisposableEffect의 사용이 적절합니다. 오류 처리와 자원 정리가 명확하게 구현되었습니다.


250-268: 미리보기 함수가 적절하게 구현되었습니다.

필요한 모든 매개변수를 제공하여 미리보기가 가능하도록 구현되었습니다.

presentation/src/main/java/view/main/navigation/MainNavigation.kt (3)

11-12: 새로운 라우트 상수를 추가했습니다.

라우트 상수를 적절하게 추가하셨습니다. 이것은 네비게이션 구조를 명확하게 정의하는 좋은 접근 방식입니다.


19-21: 새로운 네비게이션 확장 함수 추가

NavController에 적절한 확장 함수를 추가하여 디메릿 포스트 화면으로 쉽게 이동할 수 있도록 하셨습니다. 옵션 파라미터도 잘 처리되었습니다.


23-33: postDemeritScreen 구현

NavGraphBuilder에 postDemeritScreen 함수를 추가하여 디메릿 포스트 화면을 composable로 등록하셨습니다. 필요한 파라미터들도 잘 전달되고 있습니다.

data/src/main/java/remote/api/auth/AdminAPI.kt (4)

22-25: 권한 변경 API 추가

권한 변경을 위한 새로운 API 메소드를 적절하게 추가하셨습니다. PATCH 메소드를 사용하는 것이 부분 업데이트에 적합합니다.


28-30: getStudentSearch 메소드 수정

메소드 이름이 변경되고 파라미터 타입이 String?에서 String으로 변경되었습니다. 이는 null 값을 허용하지 않도록 변경된 것인데, 호출하는 코드에서 null 체크가 필요할 수 있습니다.

이 변경이 기존 코드에 영향을 미치지 않는지 확인해주세요. 특히 이 메소드를 호출하는 부분에서 null 값을 전달했을 가능성이 있습니다.


32-36: 경로 변수를 사용한 API 엔드포인트 개선

하드코딩된 "user_id" 대신 경로 변수 "{user_id}"를 사용하도록 개선하셨습니다. 이는 더 유연한 API 구현을 가능하게 합니다.


41-45: clean API 엔드포인트 경로 개선

마찬가지로 postClean API에서도 경로 변수를 사용하도록 개선하셨습니다. 이전 하드코딩된 방식보다 더 나은 접근 방식입니다.

presentation/src/main/java/component/combinationvIew/DoMaCombinationView.kt (1)

29-58: DomaCombinationView 구현

Scaffold와 조건부 라우트 렌더링 구현이 잘 되어 있습니다. 각 네비게이션 대상별로 적절한 라우트를 렌더링하고 필요한 콜백을 전달합니다.

다만, when 표현식이 exhaustive하기 때문에 DomaNavBarItemType이 추가될 경우 이 코드도 수정해야 합니다. 기본 케이스(else)를 추가하는 것을 고려해볼 수 있습니다.

presentation/src/main/java/view/main/screen/PostDemeritSearchScreen.kt (2)

41-60: PostDemeritSearchRoute 구현이 잘 되었습니다.

ViewModel에서 상태를 수집하고 화면에 전달하는 패턴이 깔끔하게 구현되었습니다.


136-142: SearchList 컴포넌트의 사용이 적절합니다.

UI 상태와 에러 처리가 잘 연결되어 있습니다.

data/src/main/java/repoistory/AdminRepositoryImpl.kt (4)

22-24: 권한 변경 기능이 잘 구현되었습니다.

새로운 changeAuthority 메소드가 추가되어 사용자 권한 관리 기능이 확장되었습니다.


25-27: 학생 검색 기능이 적절히 구현되었습니다.

getStudentSearch 메소드가 추가되어 이름으로 학생을 검색할 수 있습니다.


31-32: 메소드 서명이 정리되었습니다.

기존의 복잡한 형식이 단순화되어 가독성이 향상되었습니다.


37-38: 메소드 서명이 정리되었습니다.

기존의 복잡한 형식이 단순화되어 가독성이 향상되었습니다.

data/src/main/java/remote/datasource/admin/AdminDataSource.kt (4)

17-17: 권한 변경 기능이 인터페이스에 잘 정의되었습니다.

changeAuthority 메소드가 인터페이스에 추가되어 권한 관리 기능이 확장되었습니다.


19-20: 학생 검색 기능이 인터페이스에 잘 정의되었습니다.

getStudentSearch 메소드가 추가되어 이름으로 학생을 검색하는 기능이 구현되었습니다.


21-21: 메소드 서명이 정리되었습니다.

기존의 복잡한 형식이 단순화되어 가독성이 향상되었습니다.


25-25: 메소드 서명이 정리되었습니다.

기존의 복잡한 형식이 단순화되어 가독성이 향상되었습니다.

.idea/other.xml (6)

61-71: 새 디바이스 구성이 추가되었습니다.

Samsung A35 디바이스 설정이 추가되었습니다. 좀 더 다양한 기기에서 테스트가 가능해졌습니다.


105-115: 새 디바이스 구성이 추가되었습니다.

Motorola moto g 5G (2022) 디바이스 설정이 추가되었습니다. 다양한 제조사 기기에 대한 테스트 지원이 강화되었습니다.


284-290: 기존 디바이스 정보가 업데이트되었습니다.

Samsung 디바이스의 코드명과 ID가 "gta7lite"에서 "gts7xllite"로 변경되었고, 화면 정보도 업데이트되었습니다.


303-313: 새 디바이스 구성이 추가되었습니다.

Samsung Galaxy Tab S8 디바이스 설정이 추가되었습니다. 태블릿 디바이스에 대한 테스트가 가능해졌습니다.


369-379: 새 디바이스 구성이 추가되었습니다.

Samsung Galaxy S21 디바이스 설정이 추가되었습니다. 최신 기기에 대한 테스트가 가능해졌습니다.


469-479: 새 디바이스 구성이 추가되었습니다.

Samsung Galaxy S21 Plus 디바이스 설정이 추가되었습니다. 다양한 크기의 기기에 대한 테스트가 가능해졌습니다.

presentation/src/main/java/viewModel/homes/HomesViewmodel.kt (11)

3-4: 모듈 임포트 확인 완료
이 섹션의 새로운 임포트들은 각 기능(코루틴, Flow, UseCase, 모델, UIState 등)에 필요한 요소로 보이며, 전체적으로 적절해 보입니다.

Also applies to: 8-8, 11-11, 13-13, 15-15, 16-23, 30-33


51-55: UIState Flow 선언에 대한 간단한 확인
_changeAuthorityUiState_isRefreshing 상태 관리는 명확하며, 목적에 맞게 잘 사용되고 있습니다.


57-59: 토큰 갱신 및 토큰 저장 상태 관리 로직
_tokenRefreshUiState_saveTokenUiState 모두 UI 상태 흐름을 정의하기에 적절하며, 가독성도 좋습니다.

Also applies to: 61-62


70-71: 학생 검색/목록 UIState 선언
_studentSearchUiState, _studentListUiState를 별도로 두어, 검색 로직과 목록 로직을 분리한 점이 명확하고 유지보수에 용이해 보입니다.

Also applies to: 73-74


82-83: SavedStateHandle을 사용한 상태 보존
roleStatestudentListSearch 상태를 SavedStateHandle로 관리하며, 프로세스가 재생성되어도 필요한 값을 보전하기에 좋은 방식입니다.


107-118: changeAuthority의 에러 처리 흐름 점검
onSuccessonFailure로 1차 분기 후 Flow 내부에서 catch를 통해 예외를 별도로 처리하는 구조는 논리적으로 잘 정리되어 있습니다.


120-122: initTokenRefresh 메서드의 간결한 초기화
토큰 상태를 다시 로딩 상태로 돌리는 단순 로직으로, 필요한 경우 외부에서 호출하여 다시 초기화하기에 충분해 보입니다.


214-232: getStudentList의 호출 여부 확인
해당 메서드는 private로 선언되어 있으며, VM 내부에서 사용하지만 외부 접근이 필요한 경우가 있다면 public으로 노출하거나 필요한 곳에서 반드시 호출되는지를 점검이 필요합니다.


244-244: 에러 상태에서 추가 파라미터 사용
Fail 상태에 두 번째 인자로 null을 제공하여 확장 기능을 확보한 것으로 보이나, UI 로직 내에서 이 값(두 번째 파라미터)을 올바르게 처리하는지 확인만 해주시면 됩니다.


255-258: onStudentSearchChange 로직
이름 검색 값을 SavedStateHandle에 즉시 반영하여 상태 복원에 유리한 구조입니다. 추가 검증 로직이나 트리밍이 필요한 경우, 이 메서드 안에서 처리해도 좋겠습니다.


260-261: 상수 정의 체크
STUDENT_SEARCHROLE_STATE 상수를 별도 키로 두어 가독성을 높이는 방식이 잘 적용되었습니다.

Comment on lines +8 to +10
fun NavController.navigationToMyPage() {
this.navigate(MyPage_loute)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

내비게이션 함수가 오타가 있는 상수를 사용합니다.

내비게이션 함수는 오타가 있는 상수를 참조하고 있습니다. 위의 상수 이름을 수정한 후에는 이 부분도 일관되게 수정해야 합니다.

fun NavController.navigationToMyPage() {
-    this.navigate(MyPage_loute)
+    this.navigate(MyPage_route)
}
📝 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
fun NavController.navigationToMyPage() {
this.navigate(MyPage_loute)
}
fun NavController.navigationToMyPage() {
this.navigate(MyPage_route)
}

}

is UsersUiState.Empty -> {
MyPageEmptyText()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

MyPageEmptyText 컴포넌트 참조 오류가 발생할 수 있습니다.

MyPageEmptyText() 컴포넌트를 사용하고 있지만, 이 파일에서 해당 컴포넌트가 임포트되지 않았습니다. 해당 컴포넌트가 존재하는지 확인하고 필요한 임포트 구문을 추가해 주세요.

+ import view.mypage.component.MyPageEmptyText // 또는 실제 경로에 맞게 수정
📝 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
MyPageEmptyText()
// At the top of the file (below the package declaration)
import view.mypage.component.MyPageEmptyText // 또는 실제 경로에 맞게 수정
// ... other import statements ...
// Somewhere later in the file, at or before line 49:
MyPageEmptyText()

Comment on lines 8 to 14
@JsonClass(generateAdapter = true)
data class AdminStudentLIstResponse (
@Json(name = "name") val name: String,
@Json(name = "penaltyPoint") val penaltyPoint: Int,
@Json(name = "roomNum") val roomNum: Int,
@Json(name = "userId") val userId: UUID,
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

클래스 이름 오타 수정 필요

데이터 클래스의 이름에 오타가 있습니다. AdminStudentLIstResponse에서 'LIst'의 'I'가 대문자로 되어 있습니다. 일관성을 위해 AdminStudentListResponse로 수정해야 합니다.

-data class AdminStudentLIstResponse (
+data class AdminStudentListResponse (
    @Json(name = "name") val name: String,
    @Json(name = "penaltyPoint") val penaltyPoint: Int,
    @Json(name = "roomNum") val roomNum: Int,
    @Json(name = "userId") val userId: UUID,
)
📝 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
@JsonClass(generateAdapter = true)
data class AdminStudentLIstResponse (
@Json(name = "name") val name: String,
@Json(name = "penaltyPoint") val penaltyPoint: Int,
@Json(name = "roomNum") val roomNum: Int,
@Json(name = "userId") val userId: UUID,
)
@JsonClass(generateAdapter = true)
data class AdminStudentListResponse (
@Json(name = "name") val name: String,
@Json(name = "penaltyPoint") val penaltyPoint: Int,
@Json(name = "roomNum") val roomNum: Int,
@Json(name = "userId") val userId: UUID,
)

Comment on lines +74 to +83
@Composable
fun NotSearchIcon(
modifier: Modifier = Modifier,
){
Icon(
painter = painterResource(id = R.drawable.notserach),
contentDescription = "mypageIcon",
modifier = modifier,
)
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

리소스 이름에 오타가 있고 contentDescription이 부정확합니다.

R.drawable.notserach에 오타가 있고, contentDescription이 "mypageIcon"으로 잘못 지정되어 있습니다.

다음과 같이 수정하세요:

fun NotSearchIcon(
    modifier: Modifier = Modifier,
){
    Icon(
-        painter = painterResource(id = R.drawable.notserach),
-        contentDescription = "mypageIcon",
+        painter = painterResource(id = R.drawable.notsearch),
+        contentDescription = "notSearchIcon",
        modifier = modifier,
    )
}

리소스 이름도 drawable 폴더에서 notserach.xmlnotsearch.xml로 변경해야 합니다.

📝 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
@Composable
fun NotSearchIcon(
modifier: Modifier = Modifier,
){
Icon(
painter = painterResource(id = R.drawable.notserach),
contentDescription = "mypageIcon",
modifier = modifier,
)
}
@Composable
fun NotSearchIcon(
modifier: Modifier = Modifier,
){
Icon(
painter = painterResource(id = R.drawable.notsearch),
contentDescription = "notSearchIcon",
modifier = modifier,
)
}

Comment on lines +1 to +2
package component.combinationvIew

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

패키지 이름에 대소문자 혼용 문제

패키지 이름 combinationvIew에 대소문자가 혼용되어 있습니다(v가 소문자, I가 대문자). 자바/코틀린 컨벤션에 따르면 패키지명은 모두 소문자여야 합니다.

패키지 이름을 combinationview로 수정하는 것이 좋습니다. 관련된 모든 임포트도 함께 수정해야 합니다.

Comment on lines +64 to +65
internal var role = authRepository.getRole()
private var refreshToken = runBlocking { authRepository.getRefreshToken().first() }
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

ViewModel 초기화 시점에 runBlocking 사용 주의
속성 초기화 과정에서 runBlocking을 호출하면 UI 스레드를 잠가, 앱 응답성에 영향을 줄 수 있습니다. 코루틴 Flow에서 값을 받아오는 부분은 suspend 함수로 전환하거나, lazy 초기화로 변경해 보시기를 권장합니다.

가능한 수정 예시(간단화된 예):

- internal var role = authRepository.getRole()
- private var refreshToken = runBlocking { authRepository.getRefreshToken().first() }

+ internal var role: String? = null
+ private var refreshToken: String? = null

init {
    viewModelScope.launch {
        role = authRepository.getRole()
        refreshToken = authRepository.getRefreshToken().first()
    }
}
📝 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
internal var role = authRepository.getRole()
private var refreshToken = runBlocking { authRepository.getRefreshToken().first() }
internal var role: String? = null
private var refreshToken: String? = null
init {
viewModelScope.launch {
role = authRepository.getRole()
refreshToken = authRepository.getRefreshToken().first()
}
}

Comment on lines +85 to +105
internal fun tokenRefresh() = viewModelScope.launch {
_isRefreshing.value = true
delay(1_000L)
refreshToken = runBlocking { authRepository.getRefreshToken().first() }
tokenRefreshUseCase(refreshToken = "Bearer ${refreshToken}")
.asResult()
.collectLatest { result ->
when (result) {
is Result.Loading -> _tokenRefreshUiState.value = TokenRefreshUiState.Loading
is Result.Success -> {
_tokenRefreshUiState.value = TokenRefreshUiState.Success(result.data)
saveToken(data = result.data)
}

is Result.Error -> {
_tokenRefreshUiState.value = TokenRefreshUiState.Error(result.exception)
_isRefreshing.value = false
}
}
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

tokenRefresh 내부의 delay(1_000L)runBlocking 사용
토큰 갱신 로직에서 인위적인 1초 지연과 runBlocking 사용은 메인 스레드 지연과 블로킹 위험을 초래할 수 있습니다. 비동기 처리의 이점을 살리려면 해당 부분 제거 또는 구조 개선을 권장합니다.

예시(간단화):

internal fun tokenRefresh() = viewModelScope.launch {
    _isRefreshing.value = true
-   delay(1_000L)
-   refreshToken = runBlocking { authRepository.getRefreshToken().first() }
+   refreshToken = authRepository.getRefreshToken().first()
    tokenRefreshUseCase("Bearer $refreshToken")
        .asResult()
        .collectLatest { result ->
            ...
        }
}

Comment on lines +124 to +137
private fun saveToken(data: GAuthLoginResponseModel) = viewModelScope.launch {
_saveTokenUiState.value = SaveTokenUiState.Loading
saveTokenUseCase(data = data)
.onSuccess {
_saveTokenUiState.value = SaveTokenUiState.Success
role = authRepository.getRole()
refreshToken = runBlocking { authRepository.getRefreshToken().first() }
_isRefreshing.value = false
}
.onFailure {
_saveTokenUiState.value = SaveTokenUiState.Error(it)
_isRefreshing.value = false
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

saveToken에서의 runBlocking 개선 제안
토큰 저장 과정에서 다시 runBlocking을 사용하면 UI가 중단될 위험이 있습니다. 코루틴 내 suspend 호출로 전환하거나, 비동기적으로 값을 갱신하도록 개선할 수 있습니다.

예시(간단화):

private fun saveToken(data: GAuthLoginResponseModel) = viewModelScope.launch {
    _saveTokenUiState.value = SaveTokenUiState.Loading
    saveTokenUseCase(data = data)
        .onSuccess {
            _saveTokenUiState.value = SaveTokenUiState.Success
-           role = authRepository.getRole()
-           refreshToken = runBlocking { authRepository.getRefreshToken().first() }
+           role = authRepository.getRole() // suspend 사용 시 launch 블록에서 호출
+           refreshToken = authRepository.getRefreshToken().first()
            _isRefreshing.value = false
        }
        .onFailure {
            _saveTokenUiState.value = SaveTokenUiState.Error(it)
            _isRefreshing.value = false
        }
}
📝 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
private fun saveToken(data: GAuthLoginResponseModel) = viewModelScope.launch {
_saveTokenUiState.value = SaveTokenUiState.Loading
saveTokenUseCase(data = data)
.onSuccess {
_saveTokenUiState.value = SaveTokenUiState.Success
role = authRepository.getRole()
refreshToken = runBlocking { authRepository.getRefreshToken().first() }
_isRefreshing.value = false
}
.onFailure {
_saveTokenUiState.value = SaveTokenUiState.Error(it)
_isRefreshing.value = false
}
}
private fun saveToken(data: GAuthLoginResponseModel) = viewModelScope.launch {
_saveTokenUiState.value = SaveTokenUiState.Loading
saveTokenUseCase(data = data)
.onSuccess {
_saveTokenUiState.value = SaveTokenUiState.Success
role = authRepository.getRole() // suspend 사용 시 launch 블록에서 호출
refreshToken = authRepository.getRefreshToken().first()
_isRefreshing.value = false
}
.onFailure {
_saveTokenUiState.value = SaveTokenUiState.Error(it)
_isRefreshing.value = false
}
}

@kimjeakwan kimjeakwan changed the title 🔀(34) :: 검색 기능을 구현했습니다. 🔀(34) :: 검색 기능을 구현 및 파일구조 변경 등 리펙토링을 했습니다. Mar 7, 2025
@kimjeakwan kimjeakwan changed the title 🔀(34) :: 검색 기능을 구현 및 파일구조 변경 등 리펙토링을 했습니다. 🔀(64) :: 검색 기능을 구현 및 파일구조 변경 등 리펙토링을 했습니다. Mar 7, 2025
data class GAuthLoginResponseModel(
val accessToken: String,
val refreshToken: String,
val accessTokenExpiresIn: String,
Copy link
Collaborator

Choose a reason for hiding this comment

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

공백 한칸 지워주세요

Comment on lines 32 to 37
)
}

}

} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

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

34번 줄과 36번 줄 삭제해주세요

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

🧹 Nitpick comments (9)
presentation/src/main/java/view/theme/color/DoMaColor.kt (6)

7-8: 색상 이름 오타 수정이 필요합니다.

색상 이름에 오타가 있습니다:

  • DARKGARYDARKGRAY로 수정해야 합니다.
  • SMAlLDARKGARYSMALLDARKGRAY로 수정해야 합니다. 또한 'l'이 소문자로 되어있어 대소문자 일관성이 없습니다.

색상 이름은 직관적으로 이해할 수 있도록 정확하게 작성하는 것이 중요합니다.

-    override val DARKGARY = Color(0xFFBEBEBE)
-    override val SMAlLDARKGARY = Color(0xFF4C4C4C)
+    override val DARKGRAY = Color(0xFFBEBEBE)
+    override val SMALLDARKGRAY = Color(0xFF4C4C4C)

5-29: 색상 이름 명명 규칙의 일관성이 필요합니다.

현재 색상 이름의 명명 규칙이 일관되지 않습니다:

  • 대문자 snake_case: MAIN, WHITE, BACKGROUND
  • 파스칼 케이스: Black, Gold, Broze(오타, Bronze가 맞음)
  • 카멜 케이스: silver

색상 이름은 모두 동일한 명명 규칙을 따르는 것이 좋습니다. 다른 상수들과 일관성을 위해 대문자 snake_case를 권장합니다.

 object DoMaColor : ColorTheme(){
     override val MAIN = Color(0xFF252525)
-    override val DARKGARY = Color(0xFFBEBEBE)
-    override val SMAlLDARKGARY = Color(0xFF4C4C4C)
-    override val Black = Color(0xFF000000)
-    override val WHITE = Color(0xFFFFFFFF)
-    override val BACKGROUND = Color(0xFF1E1E1E)
+    override val DARKGRAY = Color(0xFFBEBEBE)
+    override val SMALL_DARKGRAY = Color(0xFF4C4C4C)
+    override val BLACK = Color(0xFF000000)
+    override val WHITE = Color(0xFFFFFFFF)
+    override val BACKGROUND = Color(0xFF1E1E1E)

     override val LIGHTGRAY = Color(0xFF555555)
     override val GRAY = Color(0xFF9AD54A)
-    override val Gold = Color(0xFFFFD651)
-    override val silver = Color(0xFFBEBEBE)
-    override val Broze = Color(0xFFF7A080)
+    override val GOLD = Color(0xFFFFD651)
+    override val SILVER = Color(0xFFBEBEBE)
+    override val BRONZE = Color(0xFFF7A080)

     override val SYSTEM = Color(0xFF14C38E) // 시스템 색상 (강조 색으로 설정)

-    override val CardShadow = Color(0xFF1A1A1A) // 카드 그림자 색상
-    override val StatusShadow = Color(0xFF141414) //
+    override val CARD_SHADOW = Color(0xFF1A1A1A) // 카드 그림자 색상
+    override val STATUS_SHADOW = Color(0xFF141414) //
 }

17-17: 중복된 색상값이 있습니다.

silver 색상(0xFFBEBEBE)과 DARKGARY 색상(0xFFBEBEBE)이 동일한 값을 가지고 있습니다. 색상 중복은 혼란을 줄 수 있으므로, 하나의 색상만 사용하거나 다른 값으로 구분하는 것이 좋습니다.

-    override val DARKGARY = Color(0xFFBEBEBE)
-    override val silver = Color(0xFFBEBEBE)
+    override val SILVER = Color(0xFFBEBEBE) // 하나의 색상으로 통합

18-18: "Broze" 오타를 수정해야 합니다.

Broze는 오타이며 Bronze가 올바른 철자입니다.

-    override val Broze = Color(0xFFF7A080)
+    override val BRONZE = Color(0xFFF7A080)

5-29: 색상 사용 목적에 대한 문서화가 필요합니다.

일부 색상에만 주석이 달려 있고 나머지는 그 목적이 명확하지 않습니다. 모든 색상에 대해 일관된 주석을 추가하면 다른 개발자들이 색상을 적절하게 사용하는 데 도움이 됩니다.

 object DoMaColor : ColorTheme(){
-    override val MAIN = Color(0xFF252525)
+    override val MAIN = Color(0xFF252525) // 메인 테마 색상
...
-    override val BLACK = Color(0xFF000000)
-    override val WHITE = Color(0xFFFFFFFF)
-    override val BACKGROUND = Color(0xFF1E1E1E)
+    override val BLACK = Color(0xFF000000) // 검정색 텍스트 및 아이콘용
+    override val WHITE = Color(0xFFFFFFFF) // 흰색 텍스트 및 아이콘용
+    override val BACKGROUND = Color(0xFF1E1E1E) // 앱 배경 색상
...

13-13: 불필요한 빈 줄 정리가 필요합니다.

코드에 여러 불필요한 빈 줄이 있습니다. 코드 가독성을 높이기 위해 불필요한 빈 줄을 제거하고 논리적 그룹 사이에만 적절한 간격을 유지하는 것이 좋습니다.

Also applies to: 26-28

presentation/src/main/java/view/main/screen/MainScreen.kt (3)

117-122: 무한 루프의 성능 영향을 고려해보세요.

현재 시간을 업데이트하기 위해 무한 루프와 1초 지연을 사용하고 있습니다. 이 방식은 배터리 소모가 클 수 있습니다. 화면이 표시될 때만 시간을 업데이트하거나, 더 긴 간격으로 업데이트하는 것을 고려해보세요.

- LaunchedEffect("Time") {
-     while (true) {
-         delay(1_000L)
-         currentTime = System.currentTimeMillis()
-     }
- }
+ LaunchedEffect("Time") {
+     while (true) {
+         currentTime = System.currentTimeMillis()
+         delay(60_000L) // 1분마다 업데이트하거나 필요에 따라 조정
+     }
+ }

193-197: 문자열 리소스 사용을 권장합니다.

"이번주 랭킹"과 같은 하드코딩된 문자열은 다국어 지원과 일관성을 위해 strings.xml 리소스 파일에 정의하는 것이 좋습니다.

- text= "이번주 랭킹",
+ text= stringResource(R.string.this_week_ranking),

247-265: 미리보기 구현이 테스트에 도움이 됩니다.

PreviewMainScreen 함수를 통해 UI를 미리 볼 수 있는 기능을 구현한 것은 UI 개발 과정에서 매우 유용합니다. 다양한 상태(로딩, 에러, 데이터 있음)에 대한 미리보기도 추가하면 더 좋을 것 같습니다.

다양한 상태를 미리 볼 수 있는 추가 프리뷰 함수를 고려해보세요:

@Composable
@Preview
fun PreviewMainScreenWithData() {
    MainScreen(
        homesUiState = HomesUiState.Success(/* 샘플 데이터 */),
        rankListCallBack = {},
        homesMyRankUiState = HomesMyRankUiState.Success(/* 샘플 데이터 */),
        onErrorToast = { _, _ -> },
        navigateToBack = {},
        myRankCallBack = {},
        onDemeritStudentClick = {},
        onStudentPatchClick = {},
        tokenRefreshUiState = TokenRefreshUiState.Success,
        tokenRefreshCallBack = {},
        initTokenRefreshCallBack = {},
        isRefreshing = false,
        role = Authority.ROLE_ADMIN
    )
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f6d567 and c826c1e.

📒 Files selected for processing (5)
  • presentation/src/main/java/view/main/screen/MainScreen.kt (1 hunks)
  • presentation/src/main/java/view/notice/component/NoticeCard.kt (1 hunks)
  • presentation/src/main/java/view/notice/screen/NoticeScreen.kt (1 hunks)
  • presentation/src/main/java/view/theme/color/ColorTheme.kt (1 hunks)
  • presentation/src/main/java/view/theme/color/DoMaColor.kt (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • presentation/src/main/java/view/notice/screen/NoticeScreen.kt
  • presentation/src/main/java/view/theme/color/ColorTheme.kt
  • presentation/src/main/java/view/notice/component/NoticeCard.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (4)
presentation/src/main/java/view/main/screen/MainScreen.kt (4)

55-84: 아키텍처 패턴을 잘 적용했습니다.

MainRoute 컴포넌트가 ViewModel의 상태를 수집하고 MainScreen에 전달하여 UI와 비즈니스 로직을 잘 분리했습니다. 이러한 아키텍처 패턴은 코드의 유지보수성과 테스트 용이성을 높입니다.


104-107: LaunchedEffect를 적절하게 사용했습니다.

초기 데이터 로딩을 위해 LaunchedEffect를 사용한 것은 좋은 방법입니다. 컴포저블이 처음 구성될 때 한 번만 실행되도록 Unit을 키로 사용하여 불필요한 API 호출을 방지했습니다.


226-229: RankingList 컴포넌트의 에러 처리가 적절합니다.

RankingList 컴포넌트에 onErrorToast 콜백을 전달하여 에러 처리를 위임하는 패턴이 잘 구현되어 있습니다. 이는 에러 처리 로직을 중앙화하고 일관성 있게 유지하는 좋은 방법입니다.


230-239: 조건부 UI 렌더링을 잘 구현했습니다.

사용자 역할에 따라 관리자 기능을 조건부로 표시하는 패턴이 잘 구현되어 있습니다. 이는 사용자 경험을 향상시키는 좋은 방법입니다.

Column(
modifier = modifier
.fillMaxSize()
.background(color = Color(0xFF1E1E1E)),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 색상값 대신 테마 색상을 사용하세요.

Color(0xFF1E1E1E)와 같은 하드코딩된 색상값을 사용하고 있습니다. 앱 전체의 일관성을 위해 테마에서 정의된 색상을 사용하는 것이 좋습니다.

- .background(color = Color(0xFF1E1E1E)),
+ .background(color = colors.background),
📝 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
.background(color = Color(0xFF1E1E1E)),
.background(color = colors.background),

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: 5

🔭 Outside diff range comments (1)
presentation/src/main/java/view/theme/color/DoMaColor.kt (1)

5-28: 🛠️ Refactor suggestion

상수 명명 규칙의 일관성 개선이 필요합니다.

현재 코드에서 상수 이름이 다양한 명명 규칙을 사용하고 있습니다:

  • SCREAMING_SNAKE_CASE: MAIN, DARKGARY, WHITE
  • camelCase: silver
  • PascalCase: Black, Gold, Broze, CardShadow

Kotlin에서 상수는 일반적으로 SCREAMING_SNAKE_CASE를 사용합니다. 일관성을 위해 모든 상수 이름을 이 규칙에 맞게 수정하는 것이 좋습니다.

 object DoMaColor : ColorTheme(){
     override val MAIN = Color(0xFF252525)
-    override val DARKGARY = Color(0xFFBEBEBE)
-    override val SMAlLDARKGARY = Color(0xFF4C4C4C)
-    override val Black = Color(0xFF000000)
+    override val DARK_GRAY = Color(0xFFBEBEBE)
+    override val SMALL_DARK_GRAY = Color(0xFF4C4C4C)
+    override val BLACK = Color(0xFF000000)
     override val WHITE = Color(0xFFFFFFFF)
     override val BACKGROUND = Color(0xFF1E1E1E)

-    override val LIGHTGRAY = Color(0xFF555555)
+    override val LIGHT_GRAY = Color(0xFF555555)
     override val GRAY = Color(0xFF9AD54A)
-    override val Gold = Color(0xFFFFD651)
-    override val silver = Color(0xFFBEBEBE)
-    override val Broze = Color(0xFFF7A080)
+    override val GOLD = Color(0xFFFFD651)
+    override val SILVER = Color(0xFFBEBEBE)
+    override val BRONZE = Color(0xFFF7A080)

     override val SYSTEM = Color(0xFF14C38E) // 시스템 색상 (강조 색으로 설정)

-    override val CardShadow = Color(0xFF1A1A1A) // 카드 그림자 색상
-    override val StatusShadow = Color(0xFF141414) //
+    override val CARD_SHADOW = Color(0xFF1A1A1A) // 카드 그림자 색상
+    override val STATUS_SHADOW = Color(0xFF141414) //
}
♻️ Duplicate comments (2)
presentation/src/main/java/view/mypage/component/DemeritList.kt (2)

49-49: ⚠️ Potential issue

MyPageEmptyText 컴포넌트 임포트가 누락되었습니다.

MyPageEmptyText 컴포넌트를 사용하고 있지만, 해당 컴포넌트에 대한 임포트 구문이 누락되어 있습니다. 컴파일 오류가 발생할 수 있습니다.

+ import view.mypage.component.MyPageEmptyText // 또는 실제 경로에 맞게 수정

85-85: 🛠️ Refactor suggestion

아이콘 로직이 반대로 되어 있습니다.

현재 로직은 확장되었을 때 아래 방향 아이콘을, 접혔을 때 위 방향 아이콘을 보여줍니다. 일반적인 UI/UX 패턴에 따르면, 접혔을 때는 확장을 나타내는 아래 방향 아이콘을, 확장되었을 때는 접기를 나타내는 위 방향 아이콘을 보여주는 것이 더 직관적입니다.

- painter = painterResource(id = if (isExpanded) R.drawable.down else R.drawable.up),
+ painter = painterResource(id = if (isExpanded) R.drawable.up else R.drawable.down),
🧹 Nitpick comments (21)
presentation/src/main/java/view/mypage/component/DemeritList.kt (3)

62-63: 사용하지 않는 'typography' 매개변수가 있습니다.

'typography' 매개변수가 사용되지 않고 있습니다. 사용하지 않는 매개변수는 밑줄(_)로 표시하는 것이 좋습니다. 또한 줄 63에 불필요한 공백이 있습니다.

- DoMaAndroidTheme {
-     colors, typography ->
+ DoMaAndroidTheme { colors, _ ->
🧰 Tools
🪛 GitHub Actions: Android CI

[warning] 62-62: Parameter 'typography' is never used, could be renamed to _


75-75: 하드코딩된 문자열을 strings.xml로 이동하세요.

"벌점 리스트"라는 문자열이 하드코딩되어 있습니다. 다국어 지원 및 일관성 있는 관리를 위해 strings.xml 리소스 파일로 이동하고 stringResource를 사용하세요.

- text = "벌점 리스트",
+ text = stringResource(R.string.demerit_list),

101-103: String 포맷 사용법 개선이 필요합니다.

현재 코드는 문자열 리소스를 사용하고 있지만, 명확한 변수 이름이 없어 가독성이 떨어집니다. R.string.stringResource 대신 더 명확한 이름을 사용하고, 문자열 포맷 방식도 개선하는 것이 좋습니다.

- text = stringResource(
-     R.string.stringResource, data.myBecause, data.penaltyPoint
- ),
+ text = stringResource(
+     R.string.demerit_description_format, 
+     data.myBecause, 
+     data.penaltyPoint
+ ),
data/src/main/java/remote/dto/auth/response/DoMaLoginResponse.kt (1)

21-22: 모델 변환 함수 로직이 명확하지 않습니다.

모델 변환 함수의 목적이 DTO에서 도메인 모델로 변환하는 것이라면, 함수명도 그 의도를 명확히 반영하도록 변경하는 것이 좋습니다. 또한 들여쓰기가 일관되지 않습니다.

-    refreshTokenExpiresIn=refreshTokenExpiresIn,
-    authority=authority
+    refreshTokenExpiresIn = refreshTokenExpiresIn,
+    authority = authority
presentation/src/main/java/component/modifier/DoMaIcon.kt (1)

15-23: contentDescription을 명확하게 작성해주세요

DoMaIcon의 contentDescription이 "버튼"으로 지정되어 있는데, 이는 매우 일반적인 설명입니다. 접근성을 위해 아이콘의 역할이나 기능을 정확히 설명하는 값으로 변경하는 것이 좋습니다.

fun DoMaIcon(
    modifier: Modifier = Modifier,
) {
    Image(
        painter = painterResource(id = R.drawable.left),
-        contentDescription = "버튼",
+        contentDescription = "뒤로가기",
        modifier = modifier
    )
}
presentation/src/main/java/view/theme/color/DoMaColor.kt (4)

7-7: 상수명 오타 수정이 필요합니다.

'DARKGARY'에 오타가 있습니다. 올바른 철자는 'DARKGRAY'입니다.

-    override val DARKGARY = Color(0xFFBEBEBE)
+    override val DARKGRAY = Color(0xFFBEBEBE)

13-13: 상수명 명명 규칙 개선이 필요합니다.

여러 단어로 구성된 상수명은 언더스코어(_)로 구분하는 것이 관례입니다.

-    override val LIGHTGRAY = Color(0xFF555555)
+    override val LIGHT_GRAY = Color(0xFF555555)

17-17: Bronze 단어 오타 수정이 필요합니다.

'Broze'는 'Bronze'의 오타입니다.

-    override val Broze = Color(0xFFF7A080)
+    override val Bronze = Color(0xFFF7A080)

25-27: 불필요한 빈 줄 제거가 필요합니다.

파일 끝에 불필요한 빈 줄이 여러 개 있습니다. 파일 끝에는 최대 한 개의 빈 줄만 있는 것이 좋습니다.

presentation/src/main/java/view/main/screen/MainScreen.kt (2)

100-100: 사용하지 않는 파라미터가 있습니다.

navigateToBack 파라미터가 선언되었지만 함수 내부에서 사용되지 않습니다. 이는 CI 파이프라인에서도 경고로 표시되었습니다.

아래 두 가지 방법 중 하나로 수정해주세요:

  1. 파라미터가 필요하다면 함수 내에서 사용하도록 구현
  2. 파라미터가 필요없다면 제거하거나 언더스코어(_)로 변경
- onStudentPatchClick: () -> Unit
+ onStudentPatchClick: () -> Unit,
+ // navigateToBack 사용 예시: 백 네비게이션 로직 추가

또는

- navigateToBack: () -> Unit,
+ _: () -> Unit, // 사용하지 않는 파라미터
🧰 Tools
🪛 GitHub Actions: Android CI

[warning] 100-100: Parameter 'navigateToBack' is never used


118-122: 시간 업데이트 로직을 최적화해주세요.

현재 무한 루프를 사용하여 1초마다 시간을 업데이트하고 있습니다. 이는 리소스 소모가 많을 수 있습니다.

아래와 같이 다음 초/분까지의 시간을 계산하여 필요한 시점에만 업데이트하는 방식을 고려해보세요:

- LaunchedEffect("Time") {
-     while (true) {
-         delay(1_000L)
-         currentTime = System.currentTimeMillis()
-     }
- }
+ LaunchedEffect("Time") {
+     while (true) {
+         val currentMillis = System.currentTimeMillis()
+         val millisUntilNextSecond = 1000 - (currentMillis % 1000)
+         delay(millisUntilNextSecond)
+         currentTime = System.currentTimeMillis()
+     }
+ }
presentation/src/main/java/view/main/component/SearchList.kt (10)

43-43: 문자열 리소스를 사용하세요.

하드코딩된 문자열 "로딩중"을 사용하고 있습니다. 다국어 지원 및 유지보수를 위해 문자열 리소스를 사용하는 것이 좋습니다.

strings.xml에 아래와 같이 리소스를 추가하고 이를 참조하세요:

- Text(text = "로딩중")
+ Text(text = stringResource(R.string.loading))

59-59: 문자열 리소스를 사용하세요.

하드코딩된 문자열 "검색 결과가 없습니다."를 사용하고 있습니다. 다국어 지원 및 유지보수를 위해 문자열 리소스를 사용하는 것이 좋습니다.

strings.xml에 아래와 같이 리소스를 추가하고 이를 참조하세요:

- Text(text = "검색 결과가 없습니다.")
+ Text(text = stringResource(R.string.search_no_results))

65-65: 문자열 리소스를 사용하세요.

하드코딩된 문자열 "로딩중"을 사용하고 있습니다. 다국어 지원 및 유지보수를 위해 문자열 리소스를 사용하는 것이 좋습니다.

strings.xml에 아래와 같이 리소스를 추가하고 이를 참조하세요:

- Text(text = "로딩중")
+ Text(text = stringResource(R.string.loading))

98-98: 사용하지 않는 파라미터 제거 또는 수정하세요.

typography 파라미터가 선언되었지만 함수 내부에서 사용되지 않습니다. 이는 CI 파이프라인에서도 경고로 표시되었습니다.

아래와 같이 수정해주세요:

- DoMaAndroidTheme { colors, typography ->
+ DoMaAndroidTheme { colors, _ ->
🧰 Tools
🪛 GitHub Actions: Android CI

[warning] 98-98: Parameter 'typography' is never used, could be renamed to _


103-103: 테마 시스템에서 색상을 사용하세요.

하드코딩된 색상값(Color(0xFF252525))을 사용하고 있습니다.

아래와 같이 테마 색상을 사용하도록 수정해주세요:

- .background(color = Color(0xFF252525), shape = RoundedCornerShape(size = 10.dp)),
+ .background(color = colors.surfaceVariant, shape = RoundedCornerShape(size = 10.dp)),

121-125: typography 스타일을 사용하세요.

직접 TextStyle을 정의하는 대신 테마의 typography 스타일을 사용하는 것이 좋습니다.

아래와 같이 수정해 보세요:

- text = "${data.roomNum}호",
- style = TextStyle(
-     fontSize = 16.sp,
-     fontWeight = FontWeight(700),
-     color = colors.WHITE,
- )
+ text = "${data.roomNum}호",
+ style = typography.titleMedium.copy(
+     color = colors.WHITE
+ )

130-134: typography 스타일을 사용하세요.

직접 TextStyle을 정의하는 대신 테마의 typography 스타일을 사용하는 것이 좋습니다.

아래와 같이 수정해 보세요:

- text = data.name,
- style = TextStyle(
-     fontSize = 16.sp,
-     fontWeight = FontWeight(600),
-     color = colors.WHITE,
- )
+ text = data.name,
+ style = typography.titleMedium.copy(
+     color = colors.WHITE
+ )

139-143: typography 스타일을 사용하세요.

직접 TextStyle을 정의하는 대신 테마의 typography 스타일을 사용하는 것이 좋습니다.

아래와 같이 수정해 보세요:

- text = "${data.penaltyPoint}점",
- style = TextStyle(
-     fontSize = 14.sp,
-     fontWeight = FontWeight(600),
-     color = colors.WHITE,
- )
+ text = "${data.penaltyPoint}점",
+ style = typography.bodyMedium.copy(
+     color = colors.WHITE
+ )

137-137: 고정 너비 대신 weight를 사용하세요.

Spacer의 고정 너비(152.dp)는 다양한 화면 크기에서 일관되지 않을 수 있습니다.

Row에 weight를 적용하여 더 반응형 레이아웃을 구현하는 것이 좋습니다:

- Spacer(modifier = Modifier.width(152.dp))
+ Spacer(modifier = Modifier.weight(1f))

또는 전체 Row 구조를 다음과 같이 수정하세요:

Row(
    modifier = Modifier
        .fillMaxWidth()
        .height(57.dp)
        .border(
            width = 1.dp,
            color = colors.GRAY,
            shape = RoundedCornerShape(size = 10.dp)
        ),
    horizontalArrangement = Arrangement.Center,
    verticalAlignment = Alignment.CenterVertically,
) {
-   Text(
-       text = "${data.roomNum}호",
-       style = TextStyle(
-           fontSize = 16.sp,
-           fontWeight = FontWeight(700),
-           color = colors.WHITE,
-       )
-   )
-   Spacer(modifier = Modifier.width(20.dp))
-   Text(
-       text = data.name,
-       style = TextStyle(
-           fontSize = 16.sp,
-           fontWeight = FontWeight(600),
-           color = colors.WHITE,
-       )
-   )
-   Spacer(modifier = Modifier.width(152.dp))
-   Text(
-       text = "${data.penaltyPoint}점",
-       style = TextStyle(
-           fontSize = 14.sp,
-           fontWeight = FontWeight(600),
-           color = colors.WHITE,
-       )
-   )
+   Text(
+       modifier = Modifier.weight(0.2f),
+       text = "${data.roomNum}호",
+       style = typography.titleMedium.copy(color = colors.WHITE)
+   )
+   Text(
+       modifier = Modifier.weight(0.6f),
+       text = data.name,
+       style = typography.titleMedium.copy(color = colors.WHITE)
+   )
+   Text(
+       modifier = Modifier.weight(0.2f),
+       text = "${data.penaltyPoint}점",
+       style = typography.bodyMedium.copy(color = colors.WHITE)
+   )
}

160-160: 너무 큰 최대 높이값이 설정되어 있습니다.

heightIn(max = 10_000.dp)는 과도하게 큰 값입니다. LazyColumn이 내용에 맞게 크기를 조정할 수 있도록 하기 위함으로 보이지만, 더 합리적인 값을 사용하거나 heightIn 자체를 제거하는 것이 좋습니다.

아래와 같이 수정하는 것을 고려해보세요:

- .heightIn(max = 10_000.dp)
+ // heightIn 제거 또는 더 합리적인 값 사용

또는 필요한 경우 최대 표시할 화면 높이에 맞게 조정:

- .heightIn(max = 10_000.dp)
+ .heightIn(max = 500.dp) // 더 합리적인 최대값
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c826c1e and 82ee5bb.

📒 Files selected for processing (15)
  • .idea/other.xml (7 hunks)
  • data/src/main/java/remote/dto/admin/request/AdminPenaltyRequest.kt (1 hunks)
  • data/src/main/java/remote/dto/admin/request/AuthorityRequest.kt (1 hunks)
  • data/src/main/java/remote/dto/auth/response/DoMaLoginResponse.kt (1 hunks)
  • presentation/src/main/java/component/designsystem/DomaSearchTextField.kt (1 hunks)
  • presentation/src/main/java/component/modifier/DoMaIcon.kt (1 hunks)
  • presentation/src/main/java/component/navigationbar/DomaNavBar.kt (1 hunks)
  • presentation/src/main/java/view/main/component/PostDemeritComponent.kt (1 hunks)
  • presentation/src/main/java/view/main/component/SearchEmptyText.kt (1 hunks)
  • presentation/src/main/java/view/main/component/SearchList.kt (1 hunks)
  • presentation/src/main/java/view/main/component/StudentPatch.kt (1 hunks)
  • presentation/src/main/java/view/main/navigation/MainNavigation.kt (1 hunks)
  • presentation/src/main/java/view/main/screen/MainScreen.kt (1 hunks)
  • presentation/src/main/java/view/mypage/component/DemeritList.kt (1 hunks)
  • presentation/src/main/java/view/theme/color/DoMaColor.kt (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • presentation/src/main/java/view/main/component/SearchEmptyText.kt
  • data/src/main/java/remote/dto/admin/request/AuthorityRequest.kt
  • data/src/main/java/remote/dto/admin/request/AdminPenaltyRequest.kt
  • presentation/src/main/java/view/main/navigation/MainNavigation.kt
  • presentation/src/main/java/view/main/component/PostDemeritComponent.kt
  • presentation/src/main/java/component/designsystem/DomaSearchTextField.kt
  • presentation/src/main/java/view/main/component/StudentPatch.kt
🧰 Additional context used
🪛 GitHub Actions: Android CI
presentation/src/main/java/component/navigationbar/DomaNavBar.kt

[warning] 24-24: Parameter 'typography' is never used, could be renamed to _

presentation/src/main/java/view/mypage/component/DemeritList.kt

[warning] 62-62: Parameter 'typography' is never used, could be renamed to _

data/src/main/java/remote/dto/auth/response/DoMaLoginResponse.kt

[error] 3-17: Unresolved reference: DoMaLoginResponseModel


[error] 3-17: Unresolved reference: DoMaLoginResponseModel


[error] 3-17: Unresolved reference: DoMaLoginResponseModel

presentation/src/main/java/view/main/component/SearchList.kt

[warning] 98-98: Parameter 'typography' is never used, could be renamed to _

presentation/src/main/java/view/main/screen/MainScreen.kt

[warning] 100-100: Parameter 'navigateToBack' is never used

🔇 Additional comments (19)
.idea/other.xml (8)

17-27: OnePlus 디바이스 추가 확인
새로운 OnePlus 디바이스 (CPH2415)가 API 34 및 지정된 화면 정보와 함께 올바르게 추가되었습니다. 추가된 옵션들이 프로젝트의 다른 디바이스 데이터와 일관성을 이루는지 최종 확인 부탁드립니다.


72-82: Samsung A35 디바이스 추가 확인
새로운 Samsung 디바이스 A35가 codename "a35x"로 추가되었습니다. 스크린 크기와 밀도 정보가 실제 디바이스 스펙과 일치하는지 검토하시기 바랍니다.


116-126: Motorola moto g 5G (2022) 디바이스 추가 확인
새로운 Motorola 디바이스가 추가되었습니다. API, 브랜드, codename 및 스크린 사양이 올바르게 지정된 것으로 보이며, 필요한 경우 실제 디바이스 스펙과 비교하여 확인해 주세요.


293-302: 기존 Samsung 디바이스 정보 업데이트 검토
기존 Samsung 디바이스의 codename과 id가 "gta7lite"에서 "gts7xllite"로 변경되었으며, 이름 및 스크린 사양도 업데이트되었습니다. 수정된 내용이 실제 디바이스 데이터를 반영하는지 재검토하시기 바랍니다.


314-324: Samsung Galaxy Tab S8 Ultra 디바이스 추가 확인
새로운 Galaxy Tab S8 Ultra 디바이스가 추가되었습니다. 제공된 API 버전, 스크린 해상도 및 밀도 정보가 정확한지 확인해 주세요.


325-335: Samsung Galaxy Tab S9 FE 5G 디바이스 추가 확인
새롭게 추가된 Galaxy Tab S9 FE 5G 디바이스의 정보가 정확하게 입력되었습니다. 스크린 사양과 API 레벨 등 모든 옵션이 기대하는 데이터와 일치하는지 추가 검증이 필요합니다.


391-401: Samsung Galaxy S21 디바이스 추가 검토
새로운 Galaxy S21 디바이스가 추가되었으며, API 및 스크린 정보가 제공되었습니다. 특히 screenDensity 값이 421로 설정된 점이 일반적인 값(예: 420)과 약간 차이가 있으므로 실제 스펙과 일치하는지 확인 부탁드립니다.


491-501: Samsung Galaxy S21 Plus 디바이스 추가 검토
Galaxy S21 Plus 디바이스가 새로운 옵션으로 추가되었습니다. screenDensity 값이 394로 설정된 점을 포함하여, 입력된 모든 정보가 실제 디바이스 스펙과 일치하는지 검토해 주시기 바랍니다.

data/src/main/java/remote/dto/auth/response/DoMaLoginResponse.kt (1)

14-14: JSON 필드 이름이 카멜케이스 규칙과 일치하지 않습니다.

다른 JSON 필드들은 모두 카멜케이스(accessToken, refreshToken 등)를 사용하고 있지만, Authority는 파스칼케이스를 사용하고 있습니다. 백엔드 API가 실제로 이렇게 응답하는지 확인하고, 가능하면 일관성을 유지하는 것이 좋습니다.

presentation/src/main/java/component/navigationbar/DomaNavBar.kt (1)

1-70: DomaNavBar 컴포넌트가 잘 구현되었습니다.

네비게이션 바 구현이 컴포즈 패턴을 잘 따르고 있으며, 깔끔하게 구성되어 있습니다. 각 아이템의 클릭 상태와 선택 상태에 따른 처리가 잘 되어 있습니다.

🧰 Tools
🪛 GitHub Actions: Android CI

[warning] 24-24: Parameter 'typography' is never used, could be renamed to _

presentation/src/main/java/component/modifier/DoMaIcon.kt (4)

24-35: 함수명과 리소스 이름에 오타가 있습니다.

SerchIconR.drawable.serach에 오타가 있습니다. 정확한 영어 철자는 'Search'입니다.

다음과 같이 수정하세요:

-fun SerchIcon(
+fun SearchIcon(
    modifier: Modifier = Modifier,
    tint: Color = Color.Unspecified
){
    Image(
-        painter = painterResource(id = R.drawable.serach),
+        painter = painterResource(id = R.drawable.search),
        contentDescription = "검색",
        modifier = modifier,
        colorFilter = if (tint != Color.Unspecified) ColorFilter.tint(tint) else null
    )
}

리소스 이름도 drawable 폴더에서 serach.xmlsearch.xml로 변경해야 합니다.


60-71: contentDescription이 부정확합니다.

NoticeIcon의 contentDescription이 "mypageIcon"으로 잘못 지정되어 있습니다. 접근성 측면에서 정확한 설명이 필요합니다.

다음과 같이 수정하세요:

fun NoticeIcon(
    modifier: Modifier = Modifier,
    isSelected: Boolean = false,
){
    Icon(
        painter = painterResource(id = R.drawable.notice),
-        contentDescription = "mypageIcon",
+        contentDescription = "noticeIcon",
        modifier = modifier,
        tint = if (isSelected) DoMaColor.MAIN else DoMaColor.WHITE
    )
}

73-82: 리소스 이름에 오타가 있고 contentDescription이 부정확합니다.

R.drawable.notserach에 오타가 있고, contentDescription이 "mypageIcon"으로 잘못 지정되어 있습니다.

다음과 같이 수정하세요:

fun NotSearchIcon(
    modifier: Modifier = Modifier,
){
    Icon(
-        painter = painterResource(id = R.drawable.notserach),
-        contentDescription = "mypageIcon",
+        painter = painterResource(id = R.drawable.notsearch),
+        contentDescription = "notSearchIcon",
        modifier = modifier,
    )
}

리소스 이름도 drawable 폴더에서 notserach.xmlnotsearch.xml로 변경해야 합니다.


37-47: HomeIcon의 컬러 로직이 명확합니다.

선택 상태에 따라 아이콘 색상이 변경되는 로직이 명확하게 구현되어 있습니다.

presentation/src/main/java/view/theme/color/DoMaColor.kt (2)

12-12: 공백 한칸 삭제해주세요


14-14: GRAY 색상값이 그레이 색상과 맞지 않습니다.

현재 GRAY 색상의 값은 Color(0xFF9AD54A)로 연두색/라임색에 가깝습니다. 이는 색상 이름과 실제 색상값이 일치하지 않아 혼란을 줄 수 있습니다. 그레이 색상으로 변경하거나 색상 이름을 실제 색상에 맞게 변경하는 것이 좋습니다.

presentation/src/main/java/view/main/screen/MainScreen.kt (3)

142-142: 테마 시스템에서 색상을 사용하세요.

하드코딩된 색상값(Color(0xFF1E1E1E))을 사용하고 있습니다. 이미 이전 리뷰에서 지적된 사항입니다.

아래와 같이 테마 색상을 사용하도록 수정해주세요:

- .background(color = Color(0xFF1E1E1E)),
+ .background(color = colors.background),

153-155: 불필요한 공백을 제거해주세요.

두 줄의 공백이 있습니다. 이전 리뷰에서 이미 지적된 사항입니다.


182-182: 테마 시스템에서 색상을 사용하세요.

하드코딩된 색상값(Color(0xFF252525))을 사용하고 있습니다. 이미 이전 리뷰에서 지적된 사항입니다.

아래와 같이 테마 색상을 사용하도록 수정해주세요:

- color = Color(0xFF252525), shape = RoundedCornerShape(size = 10.dp)
+ color = colors.surfaceVariant, shape = RoundedCornerShape(size = 10.dp)

package remote.dto.auth.response

import model.auth.response.GAuthLoginResponseModel
import model.auth.response.DoMaLoginResponseModel
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

모델 참조 오류를 수정해주세요.

파이프라인 오류에서 알 수 있듯이 DoMaLoginResponseModel 클래스를 찾을 수 없습니다. 올바른 경로로 임포트가 되었는지 확인하거나, 해당 모델 클래스가 존재하는지 확인해주세요.

🧰 Tools
🪛 GitHub Actions: Android CI

[error] 3-17: Unresolved reference: DoMaLoginResponseModel


[error] 3-17: Unresolved reference: DoMaLoginResponseModel


[error] 3-17: Unresolved reference: DoMaLoginResponseModel

)
fun GAuthLoginResponse.toLogin()= GAuthLoginResponseModel(

fun DoMaLoginResponseModel.toLogin()= DoMaLoginResponseModel(
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

확장 함수 방향이 잘못되었습니다.

현재 코드는 DoMaLoginResponseModel에 대한 확장 함수로 정의되어 있으나, DTO에서 모델로 변환하는 것이 일반적인 패턴입니다. 아래와 같이 변경해주세요:

-fun DoMaLoginResponseModel.toLogin()= DoMaLoginResponseModel(
+fun DoMaLoginResponse.toModel() = DoMaLoginResponseModel(
📝 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
fun DoMaLoginResponseModel.toLogin()= DoMaLoginResponseModel(
fun DoMaLoginResponse.toModel() = DoMaLoginResponseModel(
🧰 Tools
🪛 GitHub Actions: Android CI

[error] 3-17: Unresolved reference: DoMaLoginResponseModel


[error] 3-17: Unresolved reference: DoMaLoginResponseModel


[error] 3-17: Unresolved reference: DoMaLoginResponseModel

import model.auth.response.DoMaLoginResponseModel
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import emumtype.Authority
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

패키지 이름에 오타가 있습니다.

emumtype 대신 enumtype으로 수정해주세요.

-import emumtype.Authority
+import enumtype.Authority
📝 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
import emumtype.Authority
import enumtype.Authority

currentDestination: DomaNavBarItemType,
setCurrentDestination: (DomaNavBarItemType) -> Unit,
) {
DoMaAndroidTheme { colors, typography ->
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

사용하지 않는 매개변수 처리 필요

DoMaAndroidTheme에서 typography 매개변수가 사용되지 않고 있습니다. 컴파일러 경고가 발생하므로 사용하지 않는 매개변수는 언더스코어(_)로 이름을 변경하는 것이 좋습니다.

-    DoMaAndroidTheme { colors, typography ->
+    DoMaAndroidTheme { colors, _ ->
📝 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
DoMaAndroidTheme { colors, typography ->
DoMaAndroidTheme { colors, _ ->
🧰 Tools
🪛 GitHub Actions: Android CI

[warning] 24-24: Parameter 'typography' is never used, could be renamed to _

object DoMaColor : ColorTheme(){
override val MAIN = Color(0xFF252525)
override val DARKGARY = Color(0xFFBEBEBE)
override val SMAlLDARKGARY = Color(0xFF4C4C4C)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

상수명의 철자와 일관성 개선이 필요합니다.

'SMAlLDARKGARY'에는 여러 문제가 있습니다:

  1. 대소문자 혼용: 'SMAlL'이 아닌 'SMALL'로 통일
  2. 오타: 'GARY'가 아닌 'GRAY'가 올바른 철자
  3. 여러 단어로 구성된 상수명은 언더스코어(_)로 구분하는 것이 관례입니다
-    override val SMAlLDARKGARY = Color(0xFF4C4C4C)
+    override val SMALL_DARK_GRAY = Color(0xFF4C4C4C)
📝 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
override val SMAlLDARKGARY = Color(0xFF4C4C4C)
override val SMALL_DARK_GRAY = Color(0xFF4C4C4C)

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: 0

🧹 Nitpick comments (1)
presentation/src/main/java/viewModel/admin/AdminViewModel.kt (1)

111-111: 불필요한 빈 줄이 있습니다.

getPenaltyList 함수와 postClean 함수 사이에 불필요한 빈 줄이 있습니다. 코드 일관성을 위해 제거하는 것이 좋을 것 같습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82ee5bb and bd0535b.

📒 Files selected for processing (4)
  • data/src/main/java/remote/dto/auth/response/GAuthLoginResponse.kt (1 hunks)
  • data/src/main/java/repoistory/UsersRepositoryImpl.kt (1 hunks)
  • presentation/src/main/java/component/navigationbar/DomaNavBar.kt (1 hunks)
  • presentation/src/main/java/viewModel/admin/AdminViewModel.kt (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • data/src/main/java/repoistory/UsersRepositoryImpl.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • presentation/src/main/java/component/navigationbar/DomaNavBar.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (8)
presentation/src/main/java/viewModel/admin/AdminViewModel.kt (5)

3-3: import 패키지 이름이 변경되었습니다.

Untill 클래스 이름이 until로 변경되었고, 이에 따라 import 문이 업데이트되었습니다. 이 변경은 코틀린 패키지 네이밍 컨벤션에 더 적합합니다.


52-52: Result 타입 참조가 일관되게 변경되었습니다.

Untill.Result 참조가 모든 위치에서 until.Result로 변경되었습니다. 이는 import 변경과 일치하며 코드베이스 전체의 일관성을 유지합니다.

Also applies to: 56-56, 60-60, 74-74, 78-78, 82-82, 95-95, 99-99, 103-103, 120-120, 124-124, 128-128


67-88: postPenalty 함수의 형식이 개선되었습니다.

함수의 포맷팅이 일관되게 수정되었습니다. 들여쓰기와 줄바꿈이 더 명확해져 가독성이 향상되었습니다.


113-116: 파라미터 들여쓰기가 개선되었습니다.

파라미터마다 한 줄씩 분리하여 가독성이 향상되었습니다. 이전 리뷰에서 "한 칸씩 띄운 이유가 무엇인가요?"라는 질문이 있었는데, 이 변경으로 그 질문에 대한 응답이 이루어진 것으로 보입니다.


40-42: getUsersName 기능이 제거되었는데 상태를 유지하는 이유가 있나요?

getUsersName 함수가 제거되었지만, 관련 상태인 _getUserNameUiState와 그 getter는 여전히 코드에 남아있습니다. 이 상태가 다른 곳에서 사용되지 않는다면 함께 제거하는 것이 좋을 것 같습니다.

data/src/main/java/remote/dto/auth/response/GAuthLoginResponse.kt (3)

6-6: 필요한 import 추가됨.

Authority enum 타입을 사용하기 위한 import가 적절하게 추가되었습니다.


21-22: toLogin() 함수 업데이트.

toLogin() 함수에 새로 추가된 authority 필드가 적절하게 포함되었습니다. 데이터 모델 변환 시 필요한 업데이트가 잘 이루어졌습니다.


14-14:

Details

❓ Verification inconclusive

Authority 필드 추가.

authority 속성이 적절하게 추가되었습니다. 다만 JSON 이름이 "Authority"로 PascalCase를 사용하고 있는데, 다른 필드들은 camelCase를 사용하고 있습니다. API 설계에 따른 것이라면 문제없으나, 일관성 측면에서 확인해보세요.


🏁 Script executed:

#!/bin/bash
# JSON 이름 컨벤션 검사
rg -A 1 '@Json\(name = "([A-Z][a-zA-Z0-9]*)"' data/src/main/java/remote/dto --glob "*.kt"

Length of output: 952


네이밍 컨벤션 재검토 요청: "Authority" JSON 필드 명 일관성 확인

  • 새로 추가된 authority 필드는 기능적으로 문제 없이 적용되었습니다.
  • 다만, 현재 @Json(name = "Authority")와 같이 PascalCase를 사용 중입니다.
  • 커밋 내 다른 DTO 파일(예: AdminPenaltyResponse.kt)에서는 PascalCase와 camelCase가 혼용되어 있는 상황입니다.
  • API 설계나 회사 가이드에 따른 결정이라면 상관없으나, 전체 네이밍 정책의 일관성을 위해 다시 한 번 확인해 주세요.

@kimjeakwan kimjeakwan merged commit 181d567 into develop Mar 8, 2025
2 checks passed
@kimjeakwan kimjeakwan deleted the feature/64-admin-PostSerchScreen branch March 8, 2025 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants