Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f9830b5
feat: 마이페이지 UI 구현
yrsel Feb 20, 2026
0610284
feat: 북마크 컨텐츠 API 연동
yrsel Feb 20, 2026
10e6009
feat: 고객 지원 및 설정 API 연동
yrsel Feb 20, 2026
48dd2b2
refactor: 홈 화면에 임시 마이페이지 확인용 진입점 생성
yrsel Feb 20, 2026
bd3b0d7
refactor: 마이페이지 activity 생성 및 콘텐츠 컴포넌트 수정
yrsel Feb 20, 2026
7112763
feat: 프로필 API 연동
yrsel Feb 20, 2026
9e55c7e
refactor: ktlintformat
yrsel Feb 20, 2026
c2c63b3
refactor: 마이그레이션으로 사용 안되는 기존 파일 제거 및 패키지 이동
yrsel Feb 21, 2026
afee69e
refactor: Profile 영역 로딩 상태 제거
yrsel Feb 26, 2026
5b605a1
refactor: 로그아웃, 회원탈퇴 시 토큰 초기화 실패시에도 로그인 화면으로 이동하도록 수정
yrsel Feb 26, 2026
828390e
refactor: 프로필 기본 이미지 Compose 제공 아이콘으로 수정
yrsel Feb 26, 2026
485af5a
refactor: 마이페이지 북마크 콘텐츠 테두리 설정 추가
yrsel Feb 26, 2026
839a9b9
refactor: 회원탈퇴 아이템 색상 수정 및 Preview 추가
yrsel Feb 26, 2026
8cf8210
refactor: MyPageScreen Content 분리
yrsel Feb 26, 2026
17fbad3
refactor: MyPageViewModel 토큰 초기화 메서드 중복 제거
yrsel Feb 26, 2026
09caa67
refactor: MyPageSettingItem 화살표 Compose 제공 Icon으로 수정
yrsel Feb 26, 2026
2aeff70
refactor: ProfileSection 로딩 상태 제거에 따른 Preview 제거
yrsel Feb 26, 2026
f3d580b
refactor: MyPageAppBar 타이틀 문자열 추출
yrsel Feb 26, 2026
54a15fc
refactor: ProfileSection 중복 적용 modifier 제거
yrsel Feb 26, 2026
f6eb327
refactor: MyPageScreen 파라미터에 on 접두사 추가
yrsel Feb 26, 2026
d91dc1d
refactor: Mypage Mapper util 패키지로 이동
yrsel Feb 26, 2026
c9cdf74
refactor: Modifier matchParentSize 수정
yrsel Feb 26, 2026
ffc304f
refactor: dialog 상태 null 분기 제거
yrsel Feb 26, 2026
08f6f05
feat: 마이페이지 프로필 영역 재시도 요청 UI 반영
yrsel Feb 27, 2026
67800ad
refactor: 기본 프로필 아이콘 크기 조절
yrsel Feb 27, 2026
67e323e
refactor: 프로필 실패 시 스낵바로 알려주도록 수정
yrsel Feb 27, 2026
83ab948
refactor: 북마크들 불러오기 실패 시 스낵바로 알려주도록 수정
yrsel Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.setting.SettingActivity"
android:name=".ui.mypage.MyPageActivity"
android:exported="false" />
<activity
android:name=".ui.login.LoginActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.on.turip.data.accounts

import com.on.turip.data.accounts.dto.MyProfileResponse
import com.on.turip.domain.accounts.Account
import com.on.turip.domain.accounts.Role

fun MyProfileResponse.toDomain(): Account =
Account(
id = id,
nickname = nickname,
role = Role.from(role),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.on.turip.data.accounts.datasource

import com.on.turip.core.result.TuripResult
import com.on.turip.data.accounts.dto.MyProfileResponse

interface AccountRemoteDataSource {
suspend fun getMyProfile(): TuripResult<MyProfileResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.on.turip.data.accounts.datasource

import com.on.turip.core.result.TuripResult
import com.on.turip.data.accounts.dto.MyProfileResponse
import com.on.turip.data.accounts.service.AccountService
import com.on.turip.data.result.safeApiCall
import javax.inject.Inject

class DefaultAccountRemoteDataSource @Inject constructor(
private val accountService: AccountService,
) : AccountRemoteDataSource {
override suspend fun getMyProfile(): TuripResult<MyProfileResponse> = safeApiCall { accountService.getMyProfile() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.on.turip.data.accounts.dto

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class MyProfileResponse(
@SerialName("id")
val id: Long,
@SerialName("nickname")
val nickname: String,
@SerialName("role")
val role: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.on.turip.data.accounts.repository

import com.on.turip.core.result.TuripResult
import com.on.turip.core.result.mapCatching
import com.on.turip.data.accounts.datasource.AccountRemoteDataSource
import com.on.turip.data.accounts.toDomain
import com.on.turip.domain.accounts.Account
import com.on.turip.domain.accounts.AccountRepository
import javax.inject.Inject

class DefaultAccountRepository @Inject constructor(
private val accountRemoteDataSource: AccountRemoteDataSource,
) : AccountRepository {
override suspend fun loadMyProfile(): TuripResult<Account> = accountRemoteDataSource.getMyProfile().mapCatching { it.toDomain() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.on.turip.data.accounts.service

import com.on.turip.data.accounts.dto.MyProfileResponse
import de.jensklingenberg.ktorfit.http.GET

interface AccountService {
@GET("accounts/me")
suspend fun getMyProfile(): MyProfileResponse
}
6 changes: 6 additions & 0 deletions android/app/src/main/java/com/on/turip/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.on.turip.di

import com.on.turip.data.accounts.datasource.AccountRemoteDataSource
import com.on.turip.data.accounts.datasource.DefaultAccountRemoteDataSource
import com.on.turip.data.bookmarks.datasource.BookmarkRemoteDataSource
import com.on.turip.data.bookmarks.datasource.DefaultBookmarkRemoteDataSource
import com.on.turip.data.content.datasource.ContentRemoteDataSource
Expand Down Expand Up @@ -64,4 +66,8 @@ abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindGuestRemoteDataSource(guestRemoteDataSource: GuestRemoteDataSource): GuestDataSource

@Binds
@Singleton
abstract fun bindAccountRemoteDataSource(defaultAccountRemoteDataSource: DefaultAccountRemoteDataSource): AccountRemoteDataSource
}
6 changes: 6 additions & 0 deletions android/app/src/main/java/com/on/turip/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.on.turip.di

import com.on.turip.data.accounts.repository.DefaultAccountRepository
import com.on.turip.data.bookmarks.repository.DefaultBookmarkRepository
import com.on.turip.data.content.repository.DefaultContentRepository
import com.on.turip.data.login.repository.DefaultAuthRepository
Expand All @@ -9,6 +10,7 @@ import com.on.turip.data.region.repository.DefaultRegionRepository
import com.on.turip.data.searchhistory.repository.DefaultSearchHistoryRepository
import com.on.turip.data.turip.repository.DefaultTuripRepository
import com.on.turip.data.userstorage.repository.DefaultUserStorageRepository
import com.on.turip.domain.accounts.AccountRepository
import com.on.turip.domain.bookmark.repository.BookmarkRepository
import com.on.turip.domain.content.repository.ContentRepository
import com.on.turip.domain.login.AuthRepository
Expand Down Expand Up @@ -62,4 +64,8 @@ abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindGuestRepository(defaultGuestRepository: DefaultGuestRepository): GuestRepository

@Binds
@Singleton
abstract fun bindAccountRepository(defaultAccountRepository: DefaultAccountRepository): AccountRepository
}
6 changes: 6 additions & 0 deletions android/app/src/main/java/com/on/turip/di/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.on.turip.di

import com.on.turip.data.accounts.service.AccountService
import com.on.turip.data.accounts.service.createAccountService
import com.on.turip.data.bookmarks.service.BookmarkService
import com.on.turip.data.bookmarks.service.createBookmarkService
import com.on.turip.data.content.service.ContentService
Expand Down Expand Up @@ -51,4 +53,8 @@ object ServiceModule {
@Provides
@Singleton
fun provideGuestService(ktorfit: Ktorfit): GuestService = ktorfit.createGuestService()

@Provides
@Singleton
fun provideAccountService(ktorfit: Ktorfit): AccountService = ktorfit.createAccountService()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.on.turip.domain.accounts

data class Account(
val id: Long,
val nickname: String,
val role: Role,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.on.turip.domain.accounts

import com.on.turip.core.result.TuripResult

interface AccountRepository {
suspend fun loadMyProfile(): TuripResult<Account>
}
16 changes: 16 additions & 0 deletions android/app/src/main/java/com/on/turip/domain/accounts/Role.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.on.turip.domain.accounts

enum class Role(
private val tag: String,
) {
MEMBER("MEMBER"),
GUEST("GUEST"),
;

companion object {
fun from(role: String): Role {
val tag = role.uppercase()
return entries.firstOrNull { it.tag == tag } ?: GUEST
}
Comment on lines +11 to +14
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

알 수 없는 역할 수신 시 경고 로그 누락

from()이 서버에서 알 수 없는 역할 문자열을 수신할 경우 아무런 경고 없이 GUEST로 폴백합니다. API 계약 위반이나 역할 추가 시 디버깅이 어려워질 수 있습니다.

🔍 제안 수정
 companion object {
     fun from(role: String): Role {
-        val tag = role.uppercase()
-        return entries.firstOrNull { it.tag == tag } ?: GUEST
+        val normalized = role.uppercase()
+        return entries.firstOrNull { it.tag == normalized } ?: run {
+            Timber.w("알 수 없는 역할 수신: $role — GUEST로 폴백합니다.")
+            GUEST
+        }
     }
 }

추가로, 람다 내부에서 it.tag == tagtag는 지역 변수(line 12)를 참조하고, it.tag는 enum의 private 필드를 참조합니다. 이름이 동일해 혼란스러울 수 있으므로 지역 변수명을 normalized처럼 구분해 주는 것이 가독성에 좋습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@android/app/src/main/java/com/on/turip/domain/accounts/Role.kt` around lines
11 - 14, The from(role: String) function in the Role enum silently falls back to
GUEST when an unknown role string is received; update it to log a warning
(including the raw received role and the normalized value) before returning
GUEST so API/contract mismatches are visible, and rename the local variable
(currently tag) to a clearer name like normalized or normalizedTag to avoid
confusion with the enum's it.tag; use the project logging facility (e.g.,
Log.w/Timber/etc.) and reference Role.from, Role.entries, and GUEST when making
the change.

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.on.turip.ui.compose.home

import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -48,6 +49,7 @@ fun HomeScreen(
onRegionClick: (String) -> Unit,
onContentClick: (UsersLikeContentModel) -> Unit,
navigateToLoginScreen: () -> Unit,
navigateToMyPage: () -> Unit,
viewModel: HomeViewModel = hiltViewModel(),
) {
val uiState: HomeUiState by viewModel.uiState.collectAsStateWithLifecycle()
Expand All @@ -71,6 +73,7 @@ fun HomeScreen(
onContentClick = onContentClick,
onRegionClick = onRegionClick,
onDomesticClick = { viewModel.updateDomesticSelected(it) },
onNavigateToMyPage = navigateToMyPage,
modifier = Modifier.padding(innerPadding),
)
}
Expand All @@ -84,6 +87,7 @@ private fun HomeScreenContent(
onContentClick: (UsersLikeContentModel) -> Unit,
onRegionClick: (String) -> Unit,
onDomesticClick: (Boolean) -> Unit,
onNavigateToMyPage: () -> Unit,
modifier: Modifier = Modifier,
) {
var keyword: String by rememberSaveable { mutableStateOf("") }
Expand Down Expand Up @@ -166,6 +170,14 @@ private fun HomeScreenContent(
regions = uiState.regionCategories,
onRegionClick = onRegionClick,
)

Text(
text = "임시 마이페이지 확인용 텍스트",
modifier =
Modifier
.padding(top = TuripTheme.spacing.large)
.clickable(onClick = onNavigateToMyPage),
)
}
}
}
Expand All @@ -184,6 +196,7 @@ private fun HomeLoadingPreview() {
onContentClick = { },
onRegionClick = { },
onDomesticClick = { },
onNavigateToMyPage = {},
modifier = Modifier.padding(innerPadding),
)
}
Expand All @@ -210,6 +223,7 @@ private fun HomeSuccessPreview() {
onContentClick = { },
onRegionClick = { },
onDomesticClick = { },
onNavigateToMyPage = {},
modifier = Modifier.padding(innerPadding),
)
}
Expand All @@ -229,6 +243,7 @@ private fun HomeServerErrorPreview() {
onContentClick = { },
onRegionClick = { },
onDomesticClick = { },
onNavigateToMyPage = {},
modifier = Modifier.padding(innerPadding),
)
}
Expand All @@ -248,6 +263,7 @@ private fun HomeNetworkErrorPreview() {
onContentClick = { },
onRegionClick = { },
onDomesticClick = { },
onNavigateToMyPage = {},
modifier = Modifier.padding(innerPadding),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fun LoginScreen(
title = stringResource(R.string.login_dialog_migration_title),
message = stringResource(R.string.login_dialog_migration_message),
confirmText = stringResource(R.string.login_dialog_confirm_text),
dismissText = stringResource(R.string.setting_logout_dialog_dismiss),
dismissText = stringResource(R.string.my_page_logout_dialog_dismiss),
onConfirmation = viewmodel::migration,
onDismissRequest = viewmodel::clearGuestData,
)
Expand Down Expand Up @@ -154,12 +154,10 @@ private fun LoginScreenContent(
.border(
border = BorderStroke(1.dp, TuripTheme.colors.gray02),
shape = TuripTheme.shape.container,
)
.background(
).background(
color = TuripTheme.colors.gray03,
shape = TuripTheme.shape.container,
)
.fillMaxWidth()
).fillMaxWidth()
.padding(vertical = TuripTheme.spacing.extraLarge),
textAlign = TextAlign.Center,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.on.turip.ui.compose.mypage

sealed interface MyPageDialogState {
data object LogoutRequired : MyPageDialogState

data object ConfirmWithdraw : MyPageDialogState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.on.turip.ui.compose.mypage

import com.on.turip.domain.accounts.Account
import com.on.turip.ui.compose.mypage.model.ProfileModel

fun Account.toUiModel(): ProfileModel =
ProfileModel(
id = id,
nickname = nickname,
imageUrl = null,
)
Loading