Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.poti.android.data.mapper.user

import com.poti.android.data.remote.dto.response.user.MyPageResponseDto
import com.poti.android.data.remote.dto.response.user.ParticipationSummaryDto
import com.poti.android.data.remote.dto.response.user.RecruitSummaryDto
import com.poti.android.domain.model.user.HistorySummary
import com.poti.android.domain.model.user.UserMyPage
import java.lang.String.format
import java.util.Locale

fun MyPageResponseDto.toDomain(): UserMyPage =
UserMyPage(
nickname = nickname,
email = email,
profileImageUrl = profileImageUrl,
ratingAvg = format(Locale.US, "%.1f", ratingAvg),
activityMessage = activityMessage,
joinedAt = joinedAt,
hasFavoriteArtist = hasFavoriteArtist,
favoriteArtistName = favoriteArtistName,
participationSummary = participationSummary.toDomain(),
recruitSummary = recruitSummary.toDomain(),
)

fun ParticipationSummaryDto.toDomain(): HistorySummary =
HistorySummary(
total = total,
inProgress = inProgress,
completed = completed,
)

fun RecruitSummaryDto.toDomain(): HistorySummary =
HistorySummary(
total = total,
inProgress = inProgress,
completed = completed,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.poti.android.data.remote.datasource
import com.poti.android.core.network.model.BaseResponse
import com.poti.android.data.remote.dto.request.user.NicknameDuplicateRequestDto
import com.poti.android.data.remote.dto.request.user.OnboardingRequestDto
import com.poti.android.data.remote.dto.response.user.MyPageResponseDto
import com.poti.android.data.remote.dto.response.user.NicknameDuplicateResponseDto
import com.poti.android.data.remote.dto.response.user.OnboardingResponseDto
import com.poti.android.data.remote.service.UserService
Expand All @@ -16,4 +17,7 @@ class UserRemoteDataSource @Inject constructor(

suspend fun postNicknameDuplicate(nicknameDuplicateRequest: NicknameDuplicateRequestDto): BaseResponse<NicknameDuplicateResponseDto> =
userService.postNicknameDuplicate(nicknameDuplicateRequest = nicknameDuplicateRequest)

suspend fun getUserMyPage(): BaseResponse<MyPageResponseDto> =
userService.getUserMyPage()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.poti.android.data.remote.dto.response.user

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

@Serializable
data class MyPageResponseDto(
@SerialName("userId")
val userId: Long,
@SerialName("nickname")
val nickname: String,
@SerialName("email")
val email: String,
@SerialName("profileImageUrl")
val profileImageUrl: String?,
@SerialName("ratingAvg")
val ratingAvg: Double,
@SerialName("activityMessage")
val activityMessage: String,
@SerialName("joinedAt")
val joinedAt: String,
@SerialName("hasFavoriteArtist")
val hasFavoriteArtist: Boolean,
@SerialName("favoriteArtistName")
val favoriteArtistName: String?,
@SerialName("participationSummary")
val participationSummary: ParticipationSummaryDto,
@SerialName("recruitSummary")
val recruitSummary: RecruitSummaryDto,
)

@Serializable
data class ParticipationSummaryDto(
@SerialName("total")
val total: Int,
@SerialName("inProgress")
val inProgress: Int,
@SerialName("completed")
val completed: Int,
)

@Serializable
data class RecruitSummaryDto(
@SerialName("total")
val total: Int,
@SerialName("inProgress")
val inProgress: Int,
@SerialName("completed")
val completed: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package com.poti.android.data.remote.service
import com.poti.android.core.network.model.BaseResponse
import com.poti.android.data.remote.dto.request.user.NicknameDuplicateRequestDto
import com.poti.android.data.remote.dto.request.user.OnboardingRequestDto
import com.poti.android.data.remote.dto.response.user.MyPageResponseDto
import com.poti.android.data.remote.dto.response.user.NicknameDuplicateResponseDto
import com.poti.android.data.remote.dto.response.user.OnboardingResponseDto
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PATCH
import retrofit2.http.POST

Expand All @@ -19,4 +21,7 @@ interface UserService {
suspend fun postNicknameDuplicate(
@Body nicknameDuplicateRequest: NicknameDuplicateRequestDto,
): BaseResponse<NicknameDuplicateResponseDto>

@GET("/api/v1/users/mypage")
suspend fun getUserMyPage(): BaseResponse<MyPageResponseDto>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package com.poti.android.data.repository

import com.poti.android.core.network.model.handleApiResponse
import com.poti.android.core.network.util.HttpResponseHandler
import com.poti.android.data.mapper.artist.toDomain
import com.poti.android.data.mapper.user.toDomain
import com.poti.android.data.remote.datasource.UserRemoteDataSource
import com.poti.android.data.remote.dto.request.user.NicknameDuplicateRequestDto
import com.poti.android.data.remote.dto.request.user.OnboardingRequestDto
import com.poti.android.domain.model.user.UserMyPage
import com.poti.android.domain.repository.UserRepository
import javax.inject.Inject

Expand Down Expand Up @@ -34,4 +37,11 @@ class UserRepositoryImpl @Inject constructor(
.getOrThrow()
.isDuplicated
}

override suspend fun getUserMyPage(): Result<UserMyPage> = httpResponseHandler.safeApiCall {
userRemoteDataSource.getUserMyPage()
.handleApiResponse()
.getOrThrow()
.toDomain()
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.poti.android.domain.repository

import com.poti.android.domain.model.user.UserMyPage

interface UserRepository {
suspend fun patchOnboarding(
nickname: String,
Expand All @@ -9,4 +11,6 @@ interface UserRepository {
suspend fun postNicknameDuplicate(
nickname: String,
): Result<Boolean>

suspend fun getUserMyPage(): Result<UserMyPage>
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import com.poti.android.presentation.history.list.model.HistoryListUiState
import com.poti.android.presentation.history.mapper.color
import com.poti.android.presentation.history.mapper.labelResId
import com.poti.android.presentation.history.mapper.statusColor
import kotlinx.serialization.Serializable

@Serializable
enum class HistoryMode {
RECRUIT,
PARTICIPATION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.poti.android.core.navigation.Route
import com.poti.android.presentation.history.list.HistoryListRoute
import com.poti.android.presentation.history.list.HistoryMode
import com.poti.android.presentation.history.manage.ParticipantManageRoute
import com.poti.android.presentation.history.participant.ParticipantDetailRoute
import com.poti.android.presentation.history.recruiter.RecruiterDetailRoute
import com.poti.android.presentation.party.detail.navigation.navigateToPartyDetail
import com.poti.android.presentation.user.component.HistorySummaryType
import kotlinx.serialization.Serializable

sealed interface HistoryRoute : Route {
@Serializable
data object HistoryList : HistoryRoute
data class HistoryList(
val mode: HistoryMode? = HistoryMode.RECRUIT,
val type: HistorySummaryType? = HistorySummaryType.ALL,
) : HistoryRoute
Comment on lines +21 to +24
Copy link
Copy Markdown

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 . -type f -name "*.kt" | xargs grep -l "enum class HistoryMode\|sealed class HistoryMode\|data class HistoryMode" | head -5

Repository: team-poti/POTI-ANDROID

Length of output: 149


🏁 Script executed:

find . -type f -name "*.kt" | xargs grep -l "enum class HistorySummaryType\|sealed class HistorySummaryType\|data class HistorySummaryType" | head -5

Repository: team-poti/POTI-ANDROID

Length of output: 152


🏁 Script executed:

rg -nA5 "^(sealed class|enum class|data class)\s+HistoryMode" --type=kt

Repository: team-poti/POTI-ANDROID

Length of output: 92


🏁 Script executed:

rg -nA5 "^(sealed class|enum class|data class)\s+HistorySummaryType" --type=kt

Repository: team-poti/POTI-ANDROID

Length of output: 92


🏁 Script executed:

rg "@Serializable|enum class HistoryMode|sealed class HistoryMode" -B2 -A5 ./app/src/main/java/com/poti/android/presentation/history/

Repository: team-poti/POTI-ANDROID

Length of output: 3454


🏁 Script executed:

rg "@Serializable|enum class HistorySummaryType|sealed class HistorySummaryType" -B2 -A5 ./app/src/main/java/com/poti/android/

Repository: team-poti/POTI-ANDROID

Length of output: 26047


🏁 Script executed:

cat ./app/src/main/java/com/poti/android/presentation/history/navigation/HistoryNavigation.kt

Repository: team-poti/POTI-ANDROID

Length of output: 3104


HistoryModeHistorySummaryType enum에 @Serializable 추가 필수

HistoryRoute.HistoryList@Serializable로 표시되어 있으므로, 포함된 모든 프로퍼티 타입도 직렬화 가능해야 합니다. 현재 HistoryModeHistorySummaryType enum 모두 @Serializable 어노테이션이 없어서 네비게이션 인자 전달 시 직렬화 실패가 발생합니다. 두 enum 정의에 @Serializable을 추가하세요.

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/poti/android/presentation/history/navigation/HistoryNavigation.kt`
around lines 23 - 26, The HistoryRoute.HistoryList data class is `@Serializable`
but its enum properties are not; add `@Serializable` to the enum declarations
HistoryMode and HistorySummaryType and import kotlinx.serialization.Serializable
so both enums become serializable and the navigation argument serialization will
succeed. Locate the enum classes named HistoryMode and HistorySummaryType and
annotate each with `@Serializable` (and ensure the kotlinx.serialization import is
present).

Comment on lines +21 to +24
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

p1: 코드레빗 말처럼 serializable 필요해보여용


@Serializable
data class ParticipantDetail(val participantId: Long) : HistoryRoute
Expand All @@ -28,8 +33,16 @@ sealed interface HistoryRoute : Route {
data class ParticipantManage(val recruitId: Long) : HistoryRoute
}

fun NavController.navigateToHistoryList() {
navigate(HistoryRoute.HistoryList)
fun NavController.navigateToHistoryList(
mode: HistoryMode,
type: HistorySummaryType,
) {
navigate(
HistoryRoute.HistoryList(
mode = mode,
type = type,
),
)
}

fun NavController.navigateToParticipantDetail(participantId: Long) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ enum class MainTab(
MY_PARTY(
iconResId = R.drawable.ic_history,
label = R.string.bottom_nav_history,
route = HistoryRoute.HistoryList,
route = HistoryRoute.HistoryList(),
),
MYPAGE(
iconResId = R.drawable.ic_mypage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ import com.poti.android.R
import com.poti.android.core.common.extension.noRippleClickable
import com.poti.android.core.designsystem.theme.PotiTheme
import com.poti.android.domain.model.user.HistorySummary
import kotlinx.serialization.Serializable

@Serializable
enum class HistorySummaryType {
ALL,
IN_PROGRESS,
FINISHED,
COMPLETED,
}

@Composable
Expand Down Expand Up @@ -98,7 +100,7 @@ fun HistorySummaryCard(
HistoryItem(
title = stringResource(R.string.user_history_ended),
count = summary.completed,
onClick = { onItemClick(HistorySummaryType.FINISHED) },
onClick = { onItemClick(HistorySummaryType.COMPLETED) },
modifier = Modifier.weight(1f),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
Expand All @@ -27,8 +26,10 @@ import com.poti.android.core.designsystem.component.navigation.PotiHeaderPrimary
import com.poti.android.core.designsystem.theme.PotiTheme
import com.poti.android.domain.model.user.HistorySummary
import com.poti.android.domain.model.user.UserMyPage
import com.poti.android.presentation.history.list.HistoryMode
import com.poti.android.presentation.user.component.BadgeButton
import com.poti.android.presentation.user.component.HistorySummaryCard
import com.poti.android.presentation.user.component.HistorySummaryType
import com.poti.android.presentation.user.component.RatingBadge
import com.poti.android.presentation.user.component.UserInfo
import com.poti.android.presentation.user.component.UserProfile
Expand All @@ -38,6 +39,7 @@ import com.poti.android.presentation.user.mypage.model.MyPageUiIntent
@Composable
fun MyPageRoute(
onNavigateToArtist: () -> Unit,
onNavigateToHistoryList: (HistoryMode, HistorySummaryType) -> Unit,
modifier: Modifier = Modifier,
viewModel: MyPageViewModel = hiltViewModel(),
) {
Expand All @@ -46,13 +48,22 @@ fun MyPageRoute(
HandleSideEffects(viewModel.sideEffect) { effect ->
when (effect) {
MyPageUiEffect.NavigateToArtist -> onNavigateToArtist()

is MyPageUiEffect.NavigateToHistoryList -> {
onNavigateToHistoryList(effect.mode, effect.tab)
}
}
}

uiState.userMyPageLoadState.onSuccess { userMyPage ->
MyPageScreen(
userMyPage = userMyPage,
onArtistClick = { viewModel.processIntent(MyPageUiIntent.OnArtistClick) }, // TODO: [예림] 선택 최애 없을 때만 이동
onHistoryClick = { mode, type ->
viewModel.processIntent(
MyPageUiIntent.OnHistoryClick(mode, type),
)
},
modifier = modifier,
)
}
Expand All @@ -62,28 +73,25 @@ fun MyPageRoute(
private fun MyPageScreen(
userMyPage: UserMyPage,
onArtistClick: () -> Unit,
onHistoryClick: (HistoryMode, HistorySummaryType) -> Unit,
modifier: Modifier = Modifier,
) {
val scrollState = rememberScrollState()
val biasText = userMyPage.favoriteArtistName ?: stringResource(R.string.user_select_favorite_artist)

Scaffold(
Column(
modifier = modifier.fillMaxSize(),
topBar = {
PotiHeaderPrimary(
title = stringResource(R.string.user_my_page_title),
firstIconRes = R.drawable.ic_setting,
onFirstIconClick = {},
secondIconRes = R.drawable.ic_alarm,
onSecondIconClick = {},
)
},
) { innerPadding ->

) {
PotiHeaderPrimary(
title = stringResource(R.string.user_my_page_title),
firstIconRes = R.drawable.ic_setting,
onFirstIconClick = {},
secondIconRes = R.drawable.ic_alarm,
onSecondIconClick = {},
)
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.verticalScroll(scrollState)
.padding(
horizontal = screenWidthDp(16.dp),
Expand Down Expand Up @@ -123,14 +131,14 @@ private fun MyPageScreen(
HistorySummaryCard(
title = stringResource(R.string.user_history_participate),
summary = userMyPage.participationSummary,
onItemClick = { type -> }, // TODO: [예림] 분철 내역 뷰 연결
onItemClick = { type -> onHistoryClick(HistoryMode.PARTICIPATION, type) },
modifier = Modifier.fillMaxWidth(),
)

HistorySummaryCard(
title = stringResource(R.string.user_history_recruit),
summary = userMyPage.recruitSummary,
onItemClick = { type -> }, // TODO: [예림] 분철 내역 뷰 연결
onItemClick = { type -> onHistoryClick(HistoryMode.RECRUIT, type) },
modifier = Modifier.fillMaxWidth(),
)
}
Expand Down Expand Up @@ -163,6 +171,7 @@ private fun ProfileScreenPreview() {
),
),
onArtistClick = {},
onHistoryClick = { _, _ -> },
modifier = Modifier,
)
}
Expand Down Expand Up @@ -194,6 +203,7 @@ private fun ProfileScreenPreview2() {
),
),
onArtistClick = {},
onHistoryClick = { _, _ -> },
modifier = Modifier,
)
}
Expand Down
Loading