Skip to content

Conversation

@alswlekk
Copy link
Collaborator

@alswlekk alswlekk commented Dec 1, 2025

🔗 관련 이슈

📙 작업 설명

  • ElderInfoViewModel에 또 다른 ViewModel을 인자로 받는 부분을 수정하고 로컬에서 어르신 정보 및 성함, id를 받아오는 형식으로 코드를 수정했습니다
  • 또한 여러 Screen에서 ElderInfoViewModel에 의존하고 있음을 확인해 결제 부분의 경우 따로 뷰모델을 생성했고, ElderInfoViewModel 및 CallTimeViewModel을 수정해 한 스크린 당 하나의 뷰모델을 받도록 수정했습니다

📸 스크린샷 또는 시연 영상 (선택)

기능 미리보기 기능 미리보기
기능 설명 기능 설명

💬 추가 설명 or 리뷰 포인트 (선택)

@alswlekk alswlekk self-assigned this Dec 1, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

엘더 ID 저장소를 메모리 기반에서 DataStore 기반 영속성으로 리팩토링했습니다. UI 계층에서 EldersInfoViewModel 의존성을 제거하고 전용 ViewModels을 사용하도록 변경했으며, 새로운 직렬화 및 Flow 기반 데이터 흐름을 도입했습니다.

Changes

Cohort / File(s) 변경 요약
Data Model 및 직렬화
app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt, app/src/main/java/com/konkuk/medicarecall/data/util/ElderIdsSerializer.kt
새로운 ElderIds 데이터 클래스 추가 및 DataStore 직렬화 구현. Base64 인코딩 JSON 형식으로 저장.
Repository 계층
app/src/main/java/com/konkuk/medicarecall/data/repository/ElderIdRepository.kt, app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt
동기 메서드 제거 및 Flow 기반 API로 전환. suspend 함수 추가 (updateElderIds, updateElderId, clearElderIds). 메모리 저장소를 DataStore로 대체.
UseCase 계층
app/src/main/java/com/konkuk/medicarecall/domain/usecase/CheckLoginStatusUseCase.kt
개별 엘더 ID 추가에서 배치 업데이트로 변경 (updateElderIds 사용).
ViewModel 및 UI - Call Time
app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/viewmodel/CallTimeViewModel.kt, app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/screen/CallTimeScreen.kt
ElderIdRepository 의존성 추가. Flow 기반 elderIds 상태 관리. CallTimeScreen에서 EldersInfoViewModel 제거.
ViewModel 및 UI - Payment
app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/viewmodel/PaymentViewModel.kt, app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/screen/PaymentScreen.kt
새로운 PaymentViewModel 생성 (ElderIdRepository 관찰). PaymentScreen에서 EldersInfoViewModel 대신 PaymentViewModel 사용.
ViewModel - Settings
app/src/main/java/com/konkuk/medicarecall/ui/feature/settings/viewmodel/EldersInfoViewModel.kt
elderNameIdMapList 속성 제거. 배치 DataStore 동기화 로직으로 변경. ensureLoaded() 제거.
기타
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt, gradle/libs.versions.toml
import 재정렬 및 AGP 버전 업데이트 (8.13.0 → 8.13.1).

Sequence Diagram(s)

sequenceDiagram
    participant UI as 🎨 UI Screen
    participant VM as 🧠 ViewModel
    participant Repo as 📦 ElderIdRepository
    participant DS as 💾 DataStore
    participant Ser as 🔑 Serializer

    Note over UI,Ser: Elder ID 저장 흐름 (New)
    UI->>VM: 엘더 ID 업데이트 요청
    VM->>Repo: updateElderIds(elderIdMap)
    Repo->>DS: dataStore.updateData { ... }
    DS->>Ser: writeTo(elderIds, output)
    Ser->>Ser: 직렬화 (JSON → Base64)
    Ser-->>DS: 저장 완료
    DS-->>Repo: 성공
    Repo-->>VM: 업데이트 완료

    Note over UI,Ser: Elder ID 조회 흐름 (New)
    UI->>VM: elderIds Flow 구독
    VM->>Repo: getElderIds()
    Repo->>DS: data.map { ... }
    DS->>Ser: readFrom(input)
    Ser->>Ser: 역직렬화 (Base64 → JSON)
    Ser-->>DS: ElderIds 객체 반환
    DS-->>Repo: Flow<Map<Int, String>>
    Repo-->>VM: elderIds 업데이트
    VM-->>UI: 상태 표시
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • 주의 영역:
    • DataStore 직렬화 구현 (ElderIdsSerializer.kt) - 인코딩/디코딩 로직 및 에러 처리 검증 필요
    • Repository 계층 API 변경 - 모든 호출 지점에서 suspend/Flow 처리가 올바른지 확인
    • ViewModels 간 의존성 재구성 - EldersInfoViewModel 제거로 인한 데이터 흐름 검증
    • 상태 관리 변경 - 메모리 기반에서 DataStore 기반으로 전환되면서의 타이밍 이슈 확인

Possibly related PRs

Suggested labels

refactor

Suggested reviewers

  • ProtossManse
  • ikseong00

Poem

🏺 메모리에서 스토어로 마이그레이션 ✨
Flow 따라 데이터 흐르고,
DataStore 에 안전히 담아,
엘더 정보 이제 영구히 머무르네 💾
리팩토링의 아름다움, 너무 좋은데~

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 반영하고 있습니다. ElderInfo 관련 시간설정, 결제 화면, 뷰모델 수정이라는 핵심 변경을 잘 요약하고 있으며 연결 이슈 #206을 명시하고 있습니다.
Linked Issues check ✅ Passed 연결 이슈 #206의 코딩 요구사항들이 PR 변경사항에서 충족되고 있습니다. 로컬 저장 방식으로의 리팩토링(DataStore 통합), 시간 설정 화면의 데이터 사용 방식 변경, 불필요한 코드 제거가 구현되어 있습니다.
Out of Scope Changes check ✅ Passed gradle 버전 업그레이드(agp 8.13.0→8.13.1)를 제외하고 모든 변경사항이 #206의 리팩토링 목표와 직접적으로 관련되어 있습니다. gradle 변경은 미미하며 전체 PR 범위와 맥락이 있습니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/elderinfo-#206

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

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (7)
app/src/main/java/com/konkuk/medicarecall/data/util/ElderIdsSerializer.kt (2)

13-15: 문서화 개선 권장

YouTube 링크 대신 구현 의도나 Base64 인코딩을 사용한 이유를 설명하는 주석이 더 적절합니다. 외부 링크는 시간이 지나면 무효화될 수 있습니다.


31-37: Base64 인코딩이 불필요할 수 있음

DataStore는 바이너리 데이터를 직접 저장할 수 있으므로 Base64 인코딩/디코딩 과정이 오버헤드를 추가합니다. 또한, 예외 발생 시 defaultValue를 반환하면 데이터 손상을 감지하기 어려울 수 있습니다.

Base64 없이 직접 JSON을 저장하는 방식을 고려해 보세요:

-            val decodedBytesBase64 = Base64.getDecoder().decode(encodedBytes)
-            val decodedJsonString = decodedBytesBase64.decodeToString()
-            Json.decodeFromString(decodedJsonString)
+            val jsonString = encodedBytes.decodeToString()
+            Json.decodeFromString(jsonString)
app/src/main/java/com/konkuk/medicarecall/domain/usecase/CheckLoginStatusUseCase.kt (1)

30-34: 관용적인 Kotlin 문법 사용 권장

put() 대신 인덱스 연산자를 사용하는 것이 더 Kotlin스럽습니다.

-            val elderIdsMap: MutableMap<Int, String> = mutableMapOf()
-            elders.forEach { elderInfo ->
-                elderIdsMap.put(elderInfo.elderId, elderInfo.name)
-            }
+            val elderIdsMap = elders.associate { it.elderId to it.name }

associate를 사용하면 더 간결하고 불변 맵을 직접 생성할 수 있습니다. updateElderIdsMap<Int, String>을 받으므로 mutable일 필요가 없습니다.

app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/viewmodel/CallTimeViewModel.kt (1)

27-29: 오타 수정 및 StateFlow 사용 권장

주석에 오타가 있습니다: "뱐환" → "변환". 또한, Compose에서 Flow 기반 상태를 노출할 때는 StateFlow를 사용하는 것이 더 일반적인 패턴입니다.

-    // Flow -> State 로 뱐환해서 보관
-    private val _elderIds = mutableStateOf<Map<Int, String>>(emptyMap())
-    val elderIds get() = _elderIds.value // UI에서 접근할 값
+    // Flow -> State 로 변환해서 보관
+    private val _elderIds = MutableStateFlow<Map<Int, String>>(emptyMap())
+    val elderIds: StateFlow<Map<Int, String>> = _elderIds.asStateFlow()

StateFlow를 사용하면 UI에서 collectAsState()로 더 자연스럽게 수집할 수 있습니다.

app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/screen/CallTimeScreen.kt (1)

68-71: CallTimeViewModel로 elderMap을 일원화한 구조는 깔끔하고, 빈 목록 케이스만 한 번 더 생각해보면 좋겠습니다.

elderMap에서 바로 elderNames/elderIds를 만들고 isAllComplete(elderIds)를 보는 흐름은 직관적입니다. 다만 isLoading == false인데 elderMap이 빈 경우(아직 등록된 어르신이 없는 상태 등)에 대한 별도 안내나 버튼 비활성 처리/문구가 없어서, 사용자 입장에선 왜 아무것도 선택되지 않는지 헷갈릴 수 있습니다.

필수는 아니지만, 예를 들어 elderMap.isEmpty()일 때 간단한 안내 문구나 다른 화면으로의 네비게이션을 추가하는 것도 고려해 보시면 좋겠습니다.

Also applies to: 88-97

app/src/main/java/com/konkuk/medicarecall/ui/feature/settings/viewmodel/EldersInfoViewModel.kt (1)

29-37: 서버 리스트와 로컬 저장소를 한 번에 동기화하는 구조는 좋고, 로컬 업데이트 실패 케이스만 분리해두면 디버깅이 더 편할 것 같습니다.

getElders() 성공 시에 바로 elderIdRepository.updateElderIds(mapped)로 전체 동기화를 하는 건 데이터 일관성 측면에서 좋습니다. 다만 이 호출이 실패하면:

  • eldersInfoList는 최신 서버 데이터로 갱신되지만
  • 로컬 저장소(결제/시간 설정 쪽에서 쓰는 ID 맵)는 이전 상태로 남아 불일치가 생길 수도 있습니다.

아래처럼 updateElderIds 부분만 한 번 감싸서 별도 로그를 남겨두면 원인 파악이 수월할 것 같아요:

.onSuccess { list ->
    eldersInfoList = list

-   // 서버 → DataStore 전체 동기화
-   val mapped = list.associate { it.elderId to it.name }
-   elderIdRepository.updateElderIds(mapped)
+   val mapped = list.associate { it.elderId to it.name }
+   runCatching { elderIdRepository.updateElderIds(mapped) }
+       .onFailure { t ->
+           Log.e("EldersInfoViewModel", "elderId 동기화 실패", t)
+       }

    error.value = null
    errorMessage = null
}

로컬 저장 실패를 사용자에게까지 노출할 필요는 없더라도, 최소한 로그로는 구분해 두는 편이 운영에 도움이 될 것 같습니다.

Also applies to: 46-49, 53-57

app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/viewmodel/PaymentViewModel.kt (1)

16-24: 결제 대상/금액 계산 로직은 단순하고 명확합니다. isPaymentSelected 캡슐화만 살짝 고민해보면 좋을 것 같아요.

  • elderMap을 Flow에서 바로 구독해서 상태로 들고 있다가 getTotalPrice()에서 size * pricePerElder로 계산하는 구조는 이해하기 쉽고 문제 없어 보입니다.
  • isPaymentSelected를 외부에서 value를 직접 건드릴 수 있는 MutableState로 공개하고 있는데, 현재는 토글 메서드만 쓰는 형태라 굳이 열어둘 필요는 없어 보입니다.

예를 들어 이런 식으로 캡슐화해 두면 API가 조금 더 안전해집니다:

-    // 결제 버튼 선택 여부
-    val isPaymentSelected = mutableStateOf(false)
+    // 결제 버튼 선택 여부
+    private val _isPaymentSelected = mutableStateOf(false)
+    val isPaymentSelected get() = _isPaymentSelected

@@
     // 네이버페이 선택 토글
     fun togglePaymentSelect() {
-        isPaymentSelected.value = !isPaymentSelected.value
+        _isPaymentSelected.value = !_isPaymentSelected.value
     }

현재 코드도 동작에는 문제 없어서, 우선순위가 높지 않다면 나중에 한 번에 정리해도 될 수준이라고 봅니다.

Also applies to: 31-38, 40-48

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50931f0 and 81c0192.

📒 Files selected for processing (12)
  • app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repository/ElderIdRepository.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/util/ElderIdsSerializer.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/domain/usecase/CheckLoginStatusUseCase.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/screen/CallTimeScreen.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/viewmodel/CallTimeViewModel.kt (3 hunks)
  • app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/screen/PaymentScreen.kt (3 hunks)
  • app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/viewmodel/PaymentViewModel.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/ui/feature/settings/viewmodel/EldersInfoViewModel.kt (1 hunks)
  • gradle/libs.versions.toml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt (1)
app/src/main/java/com/konkuk/medicarecall/data/repository/ElderIdRepository.kt (1)
  • getElderIds (9-9)
🪛 GitHub Actions: Android CI
app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt

[error] 4-4: Detekt: Missing trailing comma before ")". [TrailingCommaOnDeclarationSite]

app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/viewmodel/CallTimeViewModel.kt

[error] 9-9: Detekt: Unused import. [NoUnusedImports]

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt

[error] 43-43: Detekt: Unexpected blank line(s) before "***". [NoBlankLineBeforeRbrace]

app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/screen/PaymentScreen.kt

[error] 55-56: Detekt: Unnecessary long whitespace. [NoMultipleSpaces]

🔇 Additional comments (5)
gradle/libs.versions.toml (1)

2-2: AGP 패치 버전 업그레이드는 좋아요!

Android Gradle Plugin을 8.13.0에서 8.13.1로 업그레이드하는 것은 안전한 패치 버전 업데이트입니다. 일반적으로 버그 픽스와 소규모 개선사항이 포함되어 있어서 하위 호환성도 유지됩니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt (1)

9-9: LGTM!

import 순서 정리만 포함된 변경입니다. 기능적 변경 없음.

app/src/main/java/com/konkuk/medicarecall/domain/usecase/CheckLoginStatusUseCase.kt (1)

38-63: 시간 설정 확인 로직 검토

현재 로직은 첫 번째 404 에러 발생 시 즉시 GoToTimeSetting으로 리턴합니다. 이는 의도된 동작인지 확인이 필요합니다 - 모든 어르신의 시간 설정을 확인하기 전에 조기 종료될 수 있습니다.

app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/viewmodel/CallTimeViewModel.kt (1)

36-49: Flow 수집 로직 검토

viewModelScope.launch 내에서 Flow를 collect하는 것은 올바른 패턴입니다. 다만, ViewModel이 clear될 때 자동으로 취소되므로 문제없습니다.

app/src/main/java/com/konkuk/medicarecall/data/repository/ElderIdRepository.kt (1)

3-9: ElderIdRepository API가 비동기·Flow 기반으로 잘 정리된 것 같습니다.

읽기(getElderIds)는 Flow<Map<Int, String>>, 쓰기 계열은 suspend 함수들로 분리되어 있어서 호출하는 쪽에서 의도가 분명하게 드러납니다. 현재 형태로는 특별히 문제 될 부분은 없어 보입니다.

Comment on lines 3 to 5
data class ElderIds(
val elderIds: Map<Int, String>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

@Serializable 어노테이션 누락 및 trailing comma 누락

  1. ElderIdsSerializer에서 Json.encodeToString()/decodeFromString()을 사용하려면 @Serializable 어노테이션이 필수입니다.
  2. 파이프라인 오류: Detekt에서 trailing comma 누락을 지적하고 있습니다.

다음과 같이 수정하세요:

+import kotlinx.serialization.Serializable
+
+@Serializable
 data class ElderIds(
-    val elderIds: Map<Int, String>
+    val elderIds: Map<Int, String>,
 )
📝 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
data class ElderIds(
val elderIds: Map<Int, String>
)
import kotlinx.serialization.Serializable
@Serializable
data class ElderIds(
val elderIds: Map<Int, String>,
)
🧰 Tools
🪛 GitHub Actions: Android CI

[error] 4-4: Detekt: Missing trailing comma before ")". [TrailingCommaOnDeclarationSite]

🤖 Prompt for AI Agents
In app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt around lines
3 to 5, the data class is missing the @Serializable annotation required for
Json.encodeToString()/decodeFromString() and Detekt is flagging a missing
trailing comma; add the kotlinx.serialization.Serializable import and annotate
the data class with @Serializable, and update the property list to include a
trailing comma (keep the multiline formatting) so the class compiles with the
serializer and satisfies Detekt.

Comment on lines 15 to 18
val Context.elderIdsDataStore by dataStore(
fileName = "elderIds",
serializer = ElderIdsSerializer,
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find and examine the ElderIdRepositoryImpl.kt file
find . -name "ElderIdRepositoryImpl.kt" -type f

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 167


🏁 Script executed:

# Also search for the file in common locations
find . -path "*/data/repositoryimpl/*" -name "*.kt" | head -20

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 1884


🏁 Script executed:

cat -n ./app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 1943


🏁 Script executed:

# Verify that 'first' is only used once in the file (line 28)
rg "\.first\(" ./app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 138


updateElderId의 스냅샷 읽기 방식으로 인한 동시성 문제 - 레이스 컨디션 발생 가능

현재 구현은 getElderIds().first()로 스냅샷을 읽은 후 별도로 updateData를 호출하는 두 단계로 나뉘어 있습니다. 여러 코루틴에서 updateElderId/updateElderIds를 동시에 호출하면, 먼저 읽은 스냅샷을 기준으로 나중 변경사항이 덮어씌워져 데이터 손실이 발생할 수 있습니다.

updateData 블록 내에서 현재 값을 기준으로 수정하면 원자성을 보장받을 수 있습니다:

     override suspend fun updateElderId(elderId: Int, name: String) {
-        val elderIds = getElderIds().first().toMutableMap()
-        elderIds[elderId] = name
-        context.elderIdsDataStore.updateData { it.copy(elderIds = elderIds) }
+        context.elderIdsDataStore.updateData { current ->
+            val updated = current.elderIds.toMutableMap()
+            updated[elderId] = name
+            current.copy(elderIds = updated)
+        }
     }
 
     override fun getElderIds(): Flow<Map<Int, String>> {
-        val preferences = context.elderIdsDataStore.data.map { it.elderIds }
-        return preferences
+        return context.elderIdsDataStore.data.map { it.elderIds }
     }
 
     override suspend fun clearElderIds() {
         context.elderIdsDataStore.updateData {
             ElderIds(elderIds = emptyMap())
         }
-    }
-
-}
+    }
+}

이 변경으로 kotlinx.coroutines.flow.first import도 더 이상 사용되지 않으니 삭제하고, 클래스 끝의 불필요한 빈 줄을 제거하면 Detekt NoBlankLineBeforeRbrace 경고도 해결됩니다.

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

🤖 Prompt for AI Agents
In
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderIdRepositoryImpl.kt
around lines 15 to 18, the code reads a snapshot with getElderIds().first() and
then calls updateData separately, which can cause race conditions and lost
updates; change updateElderId/updateElderIds to perform all read-modify-write
logic inside the DataStore.updateData { current -> ... } lambda so updates are
atomic, remove the now-unused kotlinx.coroutines.flow.first import, and delete
the stray blank line at the end of the class to satisfy Detekt
NoBlankLineBeforeRbrace.

Comment on lines 40 to 49
override suspend fun writeTo(t: ElderIds, output: OutputStream) {
val json = Json.Default.encodeToString(t)
val bytes = json.toByteArray()
val encodedBytesBase64 = Base64.getEncoder().encode(bytes)
withContext(Dispatchers.IO) {
output.use {
it.write(encodedBytesBase64)
}
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -type f -name "ElderIds.kt" -o -name "*ElderIds*" | head -20

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 249


🏁 Script executed:

fd "ElderIds.kt"

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 143


🏁 Script executed:

cat -n "app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt"

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 215


🏁 Script executed:

rg "class ElderIds" --type=kotlin

Repository: Medicare-Call/Medicare-Call-Android

Length of output: 164


Add @Serializable annotation to ElderIds class

The Json.Default.encodeToString(t) call requires the ElderIds class to be annotated with @Serializable. Currently, the annotation is missing from the class definition in app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt. Add the annotation and import kotlinx.serialization.Serializable:

import kotlinx.serialization.Serializable

@Serializable
data class ElderIds(
    val elderIds: Map<Int, String>
)

Without this, Json.Default.encodeToString() will fail at runtime.

🤖 Prompt for AI Agents
In app/src/main/java/com/konkuk/medicarecall/data/model/ElderIds.kt (where the
ElderIds data class is defined), the class is missing the kotlinx.serialization
@Serializable annotation required by Json.Default.encodeToString; add the import
statement import kotlinx.serialization.Serializable and annotate the data class
with @Serializable (i.e. place @Serializable immediately above the data class
declaration), then rebuild to ensure the serialization library recognizes the
type at compile time.

Comment on lines +8 to +9
import com.konkuk.medicarecall.data.repository.ElderIdRepository
import com.konkuk.medicarecall.data.repository.EldersInfoRepository
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

사용하지 않는 import 제거 필요

파이프라인 오류: EldersInfoRepository import가 사용되지 않습니다.

 import com.konkuk.medicarecall.data.repository.ElderIdRepository
-import com.konkuk.medicarecall.data.repository.EldersInfoRepository
 import com.konkuk.medicarecall.data.repository.SetCallRepository
📝 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 com.konkuk.medicarecall.data.repository.ElderIdRepository
import com.konkuk.medicarecall.data.repository.EldersInfoRepository
import com.konkuk.medicarecall.data.repository.ElderIdRepository
🧰 Tools
🪛 GitHub Actions: Android CI

[error] 9-9: Detekt: Unused import. [NoUnusedImports]

🤖 Prompt for AI Agents
In
app/src/main/java/com/konkuk/medicarecall/ui/feature/login/carecall/viewmodel/CallTimeViewModel.kt
around lines 8-9, remove the unused import of
com.konkuk.medicarecall.data.repository.EldersInfoRepository; keep only the
imports actually referenced (e.g., ElderIdRepository) and run your IDE's
"Optimize Imports" or Kotlin lint to ensure no other unused imports remain so
the pipeline error is resolved.

Comment on lines +52 to +56
val elderMap = paymentViewModel.elderMap
val elders = elderMap.values.toList()
var isClicked by remember { mutableStateOf(false) }
val elders = elderInfoViewModel.eldersInfoList.map { it.name }
val totalAmount = paymentViewModel.getTotalPrice() // Assuming 29,000 is the monthly fee per elder

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

isClicked 로컬 상태가 더 이상 갱신되지 않아 결제 UI가 항상 비활성 상태입니다.

지금 구조에서는:

  • ButtononClickpaymentViewModel.togglePaymentSelect()만 호출하고
  • isClicked는 어디에서도 변경되지 않아서 항상 false인 상태로 남습니다.
  • 하지만 실제 UI에서는 isClicked를 이용해 네이버페이 버튼 border 색, CTA 버튼 타입, navigateToNaverPay() 호출 여부를 모두 결정하고 있어서, 사용자가 아무리 눌러도 결제 버튼이 활성화되지 않는 문제가 생깁니다.

PaymentViewModel.isPaymentSelected를 단일 소스로 사용하도록 바꾸면 자연스럽게 해결됩니다. 예시는 다음과 같습니다(Detekt의 NoMultipleSpaces 경고까지 함께 정리):

-    val elderMap = paymentViewModel.elderMap
-    val elders = elderMap.values.toList()
-    var isClicked by remember { mutableStateOf(false) }
-    val totalAmount = paymentViewModel.getTotalPrice()  // Assuming 29,000 is the monthly fee per elder
+    val elderMap = paymentViewModel.elderMap
+    val elders = elderMap.values.toList()
+    val isClicked by paymentViewModel.isPaymentSelected
+    val totalAmount = paymentViewModel.getTotalPrice() // Assuming 29,000 is the monthly fee per elder
@@
-            Button(
+            Button(
                 modifier = modifier
                     .fillMaxWidth()
                     .padding(vertical = 18.dp),
-                onClick = { paymentViewModel.togglePaymentSelect() },
+                onClick = { paymentViewModel.togglePaymentSelect() },
@@
             Spacer(modifier = modifier.weight(1f))
             CTAButton(
                 type = if (isClicked) CTAButtonType.GREEN else CTAButtonType.DISABLED,
                 text = "결제하기",
                 onClick = { if (isClicked) navigateToNaverPay() },
             )

이렇게 바꾸면:

  • 네이버페이 버튼 클릭 시 ViewModel의 선택 상태가 바뀌고
  • 그 상태를 isClicked로 그대로 바라보면서 border 색/CTA 활성화 여부가 함께 갱신됩니다.
  • 아울러 getTotalPrice() 줄에서 두 칸 공백을 한 칸으로 줄여 Detekt: NoMultipleSpaces 경고도 같이 해결됩니다.

Also applies to: 139-166

🧰 Tools
🪛 GitHub Actions: Android CI

[error] 55-56: Detekt: Unnecessary long whitespace. [NoMultipleSpaces]

🤖 Prompt for AI Agents
In
app/src/main/java/com/konkuk/medicarecall/ui/feature/login/payment/screen/PaymentScreen.kt
around lines 52-56 (and similarly where applicable at 139-166), remove the local
mutableState isClicked and instead read the selection state from
PaymentViewModel (e.g., collectAsState()/observeAsState on
paymentViewModel.isPaymentSelected) so the UI reacts to ViewModel changes;
update the Button onClick to only call paymentViewModel.togglePaymentSelect()
(no local state mutation), use the collected ViewModel state for border
color/CTA enablement and to decide navigateToNaverPay(), and fix the double
space in the getTotalPrice() line to eliminate the Detekt NoMultipleSpaces
warning.

@ProtossManse ProtossManse changed the base branch from develop to refactor/elderid-#177 December 1, 2025 08:02
@alswlekk alswlekk merged commit fc237af into refactor/elderid-#177 Dec 1, 2025
1 of 2 checks passed
@alswlekk alswlekk deleted the refactor/elderinfo-#206 branch December 1, 2025 08:09
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.

[Refactor] elderInfo 관련 시간 설정 부분 수정

2 participants