-
Notifications
You must be signed in to change notification settings - Fork 0
[feat/#28] mypage api #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis PR adds complete MyPage and Career management functionality, including DI wiring for new services, repository implementations, request/response DTOs, Retrofit service interfaces, view models for state management, and updates to UI screens and navigation to integrate with the new backend APIs. Changes
Sequence DiagramssequenceDiagram
participant UI as CareerEditScreen
participant VM as CareerViewModel
participant Repo as CareerRepositoryImpl
participant Svc as CareerService
participant API as Backend API
rect rgb(200, 230, 255)
Note over UI,API: Load Career on Init
UI->>VM: loadCareer(careerId)
VM->>Repo: getCareer(careerId)
Repo->>Svc: careerService.getCareer()
Svc->>API: GET /careers/{careerId}
API-->>Svc: BaseResponse<CareerDto>
Svc-->>Repo: BaseResponse
Repo->>Repo: map success to Result.success
Repo-->>VM: Result<CareerDto>
VM->>VM: update _selectedCareer
VM-->>UI: selectedCareer StateFlow update
UI->>UI: initialize form fields from career data
end
rect rgb(230, 200, 255)
Note over UI,API: Update Career on Save
UI->>UI: onSaveClick() with form values
UI->>VM: updateCareer(careerId, CareerUpdateRequestDto)
VM->>Repo: updateCareer(careerId, request)
Repo->>Svc: careerService.updateCareer()
Svc->>API: PUT /careers/{careerId}
API-->>Svc: BaseResponse<CareerDto>
Svc-->>Repo: BaseResponse
Repo->>Repo: map to Result
Repo-->>VM: Result<CareerDto>
VM->>VM: reload via loadMyCareers()
VM-->>UI: state update & navigate back
end
sequenceDiagram
participant UI as MypageScreen
participant VM as MypageViewModel
participant Repo as MypageRepositoryImpl
participant Svc as MypageService
participant API as Backend API
rect rgb(230, 255, 200)
Note over UI,API: Load User Summary
UI->>VM: loadUserSummary()
VM->>Repo: getUserSummary()
Repo->>Svc: mypageService.getUserSummary()
Svc->>API: GET /users/summary
API-->>Svc: BaseResponse<MyPageUserSummaryDto>
Svc-->>Repo: BaseResponse
Repo->>Repo: extract data & return Result.success
Repo-->>VM: Result<MyPageUserSummaryDto>
VM->>VM: update _userSummary StateFlow
VM-->>UI: re-render with summary (name, major, status)
end
rect rgb(255, 230, 200)
Note over UI,API: Update Profile
UI->>UI: ProfileEditScreen onSaveClick
UI->>VM: updateProfile(name, major, mentor, jobSeeking)
VM->>Repo: updateProfile(UpdateProfileRequestDto)
Repo->>Svc: mypageService.updateProfile()
Svc->>API: PATCH /users/myprofile
API-->>Svc: ProfileUpdateResponse
Svc-->>Repo: response
Repo->>Repo: check isSuccess & map to Result.success
Repo-->>VM: Result<Unit>
VM->>VM: reload profile & summary on success
VM-->>UI: navigate back + refresh summary
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (1)
app/src/main/java/com/hsLink/hslink/data/service/mypage/MypageService.kt (1)
9-9: Remove unused import.
UserProfileDtois imported but not referenced in this file.Apply this diff:
-import com.hsLink.hslink.data.dto.response.mypage.UserProfileDto
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
app/src/main/java/com/hsLink/hslink/data/di/NetworkModule.kt(2 hunks)app/src/main/java/com/hsLink/hslink/data/di/RepositoryModule.kt(2 hunks)app/src/main/java/com/hsLink/hslink/data/di/ServiceModule.kt(2 hunks)app/src/main/java/com/hsLink/hslink/data/dto/request/common/JobType.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/dto/request/mypage/UpdateProfileRequestDto.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/dto/request/onboarding/CareerRequest.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/dto/response/CareerResponse.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/dto/response/mypage/MyPageUserProfileDto.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/dto/response/mypage/MyPageUserSummaryDto.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/dto/response/mypage/ProfileUpdateResponse.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/repositoryimpl/CareerRepositoryImpl.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/repositoryimpl/mypage/MypageRepositoryImpl.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/service/CareerService.kt(1 hunks)app/src/main/java/com/hsLink/hslink/data/service/mypage/MypageService.kt(1 hunks)app/src/main/java/com/hsLink/hslink/domain/repository/CareerRepository.kt(1 hunks)app/src/main/java/com/hsLink/hslink/domain/repository/mypage/MypageRepository.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/mypage/navigation/career/CareerEditNavigation.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/career/CareerEditScreen.kt(8 hunks)app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/main/MypageScreen.kt(3 hunks)app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/profile/ProfileEditScreen.kt(13 hunks)app/src/main/java/com/hsLink/hslink/presentation/mypage/viewmodel/CareerViewModel.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/mypage/viewmodel/MypageViewModel.kt(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
app/src/main/java/com/hsLink/hslink/presentation/mypage/viewmodel/MypageViewModel.kt (3)
app/src/main/java/com/hsLink/hslink/data/repositoryimpl/mypage/MypageRepositoryImpl.kt (2)
getUserSummary(48-59)getUserProfile(16-33)app/src/main/java/com/hsLink/hslink/data/service/mypage/MypageService.kt (3)
getUserSummary(24-25)getUserProfile(15-26)getUserProfile(16-17)app/src/main/java/com/hsLink/hslink/domain/repository/mypage/MypageRepository.kt (3)
getUserSummary(14-14)getUserProfile(9-16)getUserProfile(10-10)
app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/career/CareerEditScreen.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)
app/src/main/java/com/hsLink/hslink/presentation/mypage/navigation/career/CareerEditNavigation.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/career/CareerEditScreen.kt (1)
CareerEditRoute(56-93)
app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/profile/ProfileEditScreen.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/mypage/component/profile/CareerCard.kt (1)
CareerCard(45-101)
🔇 Additional comments (6)
app/src/main/java/com/hsLink/hslink/data/dto/response/mypage/ProfileUpdateResponse.kt (1)
5-10: LGTM!The response DTO structure is clean and follows standard serialization patterns for API responses.
app/src/main/java/com/hsLink/hslink/data/dto/request/mypage/UpdateProfileRequestDto.kt (1)
6-13: LGTM!The nullable fields with default null values correctly support partial updates for PATCH semantics, allowing callers to specify only the fields they want to update.
app/src/main/java/com/hsLink/hslink/data/dto/response/mypage/MyPageUserSummaryDto.kt (1)
6-15: LGTM!The DTO structure is clean with appropriate field types. The inline Korean comments provide helpful context for the development team.
app/src/main/java/com/hsLink/hslink/data/di/ServiceModule.kt (1)
27-31: LGTM!The DI provider for
MypageServicefollows the established pattern and is correctly configured with singleton scope.app/src/main/java/com/hsLink/hslink/data/di/NetworkModule.kt (1)
80-84: LGTM!The DI provider for
CareerServiceis correctly implemented with singleton scope and follows the established pattern in this module.app/src/main/java/com/hsLink/hslink/data/service/mypage/MypageService.kt (1)
16-25: Standardize response wrapping across MypageService endpoints for consistent error handling.The inconsistency is confirmed. The three endpoints handle HTTP-level errors differently:
getUserProfile()returnsResponse<BaseResponse<>>— HTTP errors are caught inresponse.isSuccessfulupdateProfile()returnsProfileUpdateResponse— HTTP errors will throw exceptionsgetUserSummary()returnsBaseResponse<>— HTTP errors will throw exceptionsWhile the repository layer currently handles each case, this creates inconsistent error handling behavior. The
ProfileUpdateResponsestructure mirrorsBaseResponse, suggestingupdateProfileshould also be wrapped inResponse<BaseResponse<>>for uniform HTTP-level error handling across all endpoints.Standardize all three endpoints to use
Response<BaseResponse<T>>wrapping to ensure consistent error handling throughout the repository layer.
| package com.hsLink.hslink.data.dto.request.common | ||
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| // data/dto/common/JobType.kt | ||
| @Serializable | ||
| enum class JobType { | ||
| PERMANENT, // 정규직 | ||
| TEMPORARY, // 계약직 | ||
| INTERN, // 인턴 | ||
| FREELANCER // 프리랜서 | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Consider relocating to common package and consolidating duplicate JobType.
Two concerns:
-
Package location: This enum is placed in
data.dto.request.common, but it's also used in response DTOs (e.g.,CareerDto). Consider moving it todata.dto.commonfor better organization. -
Duplicate enum: Based on imports in
CareerResponse.kt, there's already aJobTypeenum inpresentation.onboarding.model. Having two separateJobTypeenums violates DRY and can cause import confusion.
Recommendation:
- Consolidate to a single
JobTypeenum indata.dto.common(ordomain.model.common) - Remove the duplicate from
presentation.onboarding.model - Update all references throughout the codebase to use the canonical version
This will prevent future bugs from mixing the two types and improve maintainability.
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| // data/dto/common/JobType.kt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect file path in comment.
The comment states data/dto/common/JobType.kt, but the actual package is com.hsLink.hslink.data.dto.request.common (line 1).
Apply this diff:
-// data/dto/common/JobType.kt
+// data/dto/request/common/JobType.kt📝 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.
| // data/dto/common/JobType.kt | |
| // data/dto/request/common/JobType.kt |
🤖 Prompt for AI Agents
In app/src/main/java/com/hsLink/hslink/data/dto/request/common/JobType.kt around
line 5, the top-of-file comment incorrectly shows the path
"data/dto/common/JobType.kt"; update that comment to the correct path matching
the package (com/hsLink/hslink/data/dto/request/common/JobType.kt) or remove the
stale path comment so it no longer misrepresents the file location.
| @Serializable | ||
| data class CareerDto( | ||
| val id: Long, | ||
| val companyName: String, | ||
| val position: String, | ||
| val jobType: JobType, | ||
| val employed: Boolean, | ||
| val startYm: String, | ||
| val endYm: String? | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ID type inconsistency and duplicate JobType enum.
Two critical issues:
-
ID type mismatch:
CareerResponse.idisInt(line 12), butCareerDto.idisLong(line 31). Since both represent career entities from the same backend, this inconsistency can cause casting errors or data loss. -
Duplicate JobType enum: The file imports
JobTypefrompresentation.onboarding.model(line 5) forCareerResponse, whileCareerDtoappears to use a differentJobTypefromdata.dto.request.common. Having two separate enums with the same name violates DRY and can lead to confusion and serialization issues.
Recommendations:
- Standardize the ID type (use
Longconsistently for all career IDs) - Consolidate to a single
JobTypeenum (preferably in thedatalayer) and remove the duplicate frompresentation.onboarding.model - Update all references to use the canonical
JobType
Apply this diff to fix the ID type:
@Serializable
data class CareerResponse(
- @SerialName("id") val id: Int,
+ @SerialName("id") val id: Long,
@SerialName("companyName") val companyName: String,
@SerialName("position") val position: String,
@SerialName("jobType") val jobType: JobType,
@SerialName("employed") val employed: Boolean,
@SerialName("startYm") val startYm: String,
@SerialName("endYm") val endYm: String?,
)Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/src/main/java/com/hsLink/hslink/data/dto/response/CareerResponse.kt
around lines 29 to 38, the CareerResponse and CareerDto disagree on id type (Int
vs Long) and two different JobType enums are being used; change
CareerResponse.id to Long to match CareerDto, replace the import of JobType from
presentation.onboarding.model with the canonical JobType from
data.dto.request.common (or the shared data-layer enum), remove the duplicate
presentation-layer enum, and update all usages/imports across the module to
reference the single data-layer JobType so serialization and type-safety are
consistent.
| composable<CareerEdit> { backStackEntry -> | ||
| val careerEdit = backStackEntry.arguments?.let { | ||
| // ← careerId 추출 | ||
| CareerEdit(careerId = it.getLong("careerId")) | ||
| } ?: CareerEdit(careerId = 0L) | ||
|
|
||
| CareerEditRoute( | ||
| paddingValues = padding, | ||
| navController = navController | ||
| navController = navController, | ||
| careerId = careerEdit.careerId // ← careerId 전달 | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't force a missing careerId into 0
CareerEditRoute (see app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/career/CareerEditScreen.kt) still treats a null id as “new career”, skipping loadCareer/updateCareer. By defaulting the bundle to CareerEdit(careerId = 0L) we now drive the screen into edit mode and fire loadCareer(0) / updateCareer(0, …), which will inevitably come back as a 404 when the argument is genuinely absent (e.g., create flow or arg loss after process recreation/deep link). Instead of inventing the sentinel, bail out when the id isn’t there:
composable<CareerEdit> { backStackEntry ->
- val careerEdit = backStackEntry.arguments?.let {
- CareerEdit(careerId = it.getLong("careerId"))
- } ?: CareerEdit(careerId = 0L)
-
- CareerEditRoute(
- paddingValues = padding,
- navController = navController,
- careerId = careerEdit.careerId // ← careerId 전달
- )
+ val args = backStackEntry.arguments
+ if (args == null || !args.containsKey("careerId")) {
+ navController.popBackStack()
+ return@composable
+ }
+
+ CareerEditRoute(
+ paddingValues = padding,
+ navController = navController,
+ careerId = args.getLong("careerId")
+ )
}That preserves the nullable contract and prevents bogus API calls.
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/mypage/navigation/career/CareerEditNavigation.kt
around lines 21–31, do not default a missing careerId to 0L; instead preserve
the nullability and pass a nullable id to the route so the screen can treat a
missing id as “create” rather than attempting to load/update id 0. Change the
extraction to produce a Long? (or pass null) when the argument is absent and
forward that nullable value into CareerEditRoute (and ensure the route/screen
handles null appropriately), removing the sentinel 0L fallback which causes
bogus API calls.
| LaunchedEffect(Unit) { | ||
| viewModel.loadUserSummary() // 또는 loadMypage() | ||
| } | ||
|
|
||
| // ← 프로필 수정 후 돌아왔을 때 새로고침 | ||
| val currentBackStackEntry by navController.currentBackStackEntryAsState() | ||
| LaunchedEffect(currentBackStackEntry) { | ||
| // 프로필 수정 화면에서 돌아왔을 때만 새로고침 | ||
| if (currentBackStackEntry?.destination?.route?.contains("mypage") == true) { | ||
| viewModel.loadUserSummary() | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid double-loading user summary on first render.
Both LaunchedEffect(Unit) and the back-stack LaunchedEffect fire on first composition because the current destination already contains “mypage”, so the screen fires two identical loadUserSummary() requests back-to-back. That extra network call shows up as duplicate loading and wastes bandwidth. Gate the second effect’s first emission (and add the needed remember/mutableStateOf imports) so it only refreshes when you actually return from another screen.
+ var hasHandledInitialBackStack by remember { mutableStateOf(false) }
@@
- LaunchedEffect(currentBackStackEntry) {
- // 프로필 수정 화면에서 돌아왔을 때만 새로고침
- if (currentBackStackEntry?.destination?.route?.contains("mypage") == true) {
- viewModel.loadUserSummary()
- }
- }
+ LaunchedEffect(currentBackStackEntry) {
+ if (!hasHandledInitialBackStack) {
+ hasHandledInitialBackStack = true
+ return@LaunchedEffect
+ }
+ if (currentBackStackEntry?.destination?.route?.contains("mypage") == true) {
+ viewModel.loadUserSummary()
+ }
+ }📝 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.
| LaunchedEffect(Unit) { | |
| viewModel.loadUserSummary() // 또는 loadMypage() | |
| } | |
| // ← 프로필 수정 후 돌아왔을 때 새로고침 | |
| val currentBackStackEntry by navController.currentBackStackEntryAsState() | |
| LaunchedEffect(currentBackStackEntry) { | |
| // 프로필 수정 화면에서 돌아왔을 때만 새로고침 | |
| if (currentBackStackEntry?.destination?.route?.contains("mypage") == true) { | |
| viewModel.loadUserSummary() | |
| } | |
| } | |
| LaunchedEffect(Unit) { | |
| viewModel.loadUserSummary() // 또는 loadMypage() | |
| } | |
| // ← 프로필 수정 후 돌아왔을 때 새로고침 | |
| val currentBackStackEntry by navController.currentBackStackEntryAsState() | |
| var hasHandledInitialBackStack by remember { mutableStateOf(false) } | |
| LaunchedEffect(currentBackStackEntry) { | |
| if (!hasHandledInitialBackStack) { | |
| hasHandledInitialBackStack = true | |
| return@LaunchedEffect | |
| } | |
| if (currentBackStackEntry?.destination?.route?.contains("mypage") == true) { | |
| viewModel.loadUserSummary() | |
| } | |
| } |
| Box { | ||
| CareerCard( | ||
| name = "투썸플레이스", | ||
| title = "영업", | ||
| dateRange = "2024.02 ~ 2024.10", // ← subtitle을 dateRange로 변경 | ||
| onClick = onCareerClick | ||
| ) | ||
| careers.forEach { career -> | ||
| CareerCard( | ||
| name = career.companyName, | ||
| title = career.position, | ||
| dateRange = "${career.startYm} ~ ${career.endYm ?: "현재"}", | ||
| onClick = { onCareerClick(career) } | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix overlapping career cards rendering
Line 359 currently iterates inside a Box, which stacks each CareerCard in the same position. With multiple careers, only the last card remains visible/clickable. Please replace the Box with a vertical layout (Column/LazyColumn) so the cards render as a list.
- Box {
- careers.forEach { career ->
- CareerCard(
- name = career.companyName,
- title = career.position,
- dateRange = "${career.startYm} ~ ${career.endYm ?: "현재"}",
- onClick = { onCareerClick(career) }
- )
- }
- }
+ Column(
+ verticalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ careers.forEach { career ->
+ CareerCard(
+ name = career.companyName,
+ title = career.position,
+ dateRange = "${career.startYm} ~ ${career.endYm ?: "현재"}",
+ onClick = { onCareerClick(career) }
+ )
+ }
+ }📝 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.
| Box { | |
| CareerCard( | |
| name = "투썸플레이스", | |
| title = "영업", | |
| dateRange = "2024.02 ~ 2024.10", // ← subtitle을 dateRange로 변경 | |
| onClick = onCareerClick | |
| ) | |
| careers.forEach { career -> | |
| CareerCard( | |
| name = career.companyName, | |
| title = career.position, | |
| dateRange = "${career.startYm} ~ ${career.endYm ?: "현재"}", | |
| onClick = { onCareerClick(career) } | |
| ) | |
| } | |
| Column( | |
| verticalArrangement = Arrangement.spacedBy(12.dp) | |
| ) { | |
| careers.forEach { career -> | |
| CareerCard( | |
| name = career.companyName, | |
| title = career.position, | |
| dateRange = "${career.startYm} ~ ${career.endYm ?: "현재"}", | |
| onClick = { onCareerClick(career) } | |
| ) | |
| } | |
| } |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/mypage/screen/profile/ProfileEditScreen.kt
around lines 357 to 365, the code uses Box { careers.forEach { ... } } which
stacks every CareerCard in the same position causing overlap; replace the Box
with a vertical layout — either Column { careers.forEach { ... } } for a simple
static list or LazyColumn { items(careers) { career -> CareerCard(...) } } for a
performant scrollable list — ensure you remove the Box and use appropriate
imports and modifiers (e.g., Modifier.fillMaxWidth() and spacing/padding) so
each CareerCard is laid out vertically and remains clickable.
| private fun getUserSummary() { | ||
| viewModelScope.launch { | ||
| _isLoading.value = true | ||
| Log.d(TAG, "Summary API 호출 시작") | ||
|
|
||
| mypageRepository.getUserSummary().fold( | ||
| onSuccess = { summary -> | ||
| _userSummary.value = summary | ||
| Log.d(TAG, "Summary API 성공: ${summary.name}") | ||
| }, | ||
| onFailure = { exception -> | ||
| Log.e(TAG, "Summary API 실패", exception) | ||
| } | ||
| ).also { | ||
| _isLoading.value = false | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restore error propagation for summary fetch.
getUserSummary() never touches _error, so a failed summary call doesn't surface to the UI and a previous error message lingers even after a successful refresh. That breaks the screen's ability to report failures and to clear stale errors after recovering. Please set _error on both branches so the state stays accurate.
- mypageRepository.getUserSummary().fold(
- onSuccess = { summary ->
- _userSummary.value = summary
- Log.d(TAG, "Summary API 성공: ${summary.name}")
- },
- onFailure = { exception ->
- Log.e(TAG, "Summary API 실패", exception)
- }
- ).also {
- _isLoading.value = false
- }
+ mypageRepository.getUserSummary().fold(
+ onSuccess = { summary ->
+ _userSummary.value = summary
+ _error.value = null
+ Log.d(TAG, "Summary API 성공: ${summary.name}")
+ },
+ onFailure = { exception ->
+ _error.value = exception.message
+ Log.e(TAG, "Summary API 실패", exception)
+ }
+ ).also {
+ _isLoading.value = false
+ }🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/mypage/viewmodel/MypageViewModel.kt
around lines 91 to 106, the getUserSummary() call never updates the _error state
so failures aren’t surfaced and stale errors persist; update the onSuccess
branch to clear _error (e.g., _error.value = null) and update the onFailure
branch to set _error to a descriptive message or the exception message/object,
ensuring both success and failure paths update _error and leave _isLoading
handling as-is.
ISSUE
❗ WORK DESCRIPTIONAdd commentMore actions
📸 SCREENSHOT
2025-11-13.12.33.07.mov
📢 TO REVIEWERS
Summary by CodeRabbit
Release Notes