Skip to content
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

[TNT-186] 트레이니 마이페이지 기능 구현 #78

Merged
merged 13 commits into from
Feb 10, 2025
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
34 changes: 24 additions & 10 deletions data/network/src/main/java/co/kr/data/network/model/UserResponse.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,27 @@ data class UserResponse(
val name: String,
val email: String,
val profileImageUrl: String,
val birthday: String?,
val memberType: MemberType,
val socialType: String,
val invitationCode: String,
val height: Double?,
val weight: Double?,
val trainer: TrainerResponse?,
val trainee: TraineeResponse?,
)

@Serializable
data class TrainerResponse(
val activeTraineeCount: Int?,
val totalTraineeCount: Int?,
val invitationCode: String?,
)

@Serializable
data class TraineeResponse(
val birthday: String?,
val age: Int?,
val height: Double,
val weight: Double,
val cautionNote: String?,
val goalContents: List<String>,
val ptGoals: List<String>,
)

fun UserResponse.toDomain(dateFormatter: DateFormatter): User {
Expand All @@ -32,11 +45,12 @@ fun UserResponse.toDomain(dateFormatter: DateFormatter): User {
id = "TODO",
name = name,
image = profileImageUrl,
birthday = birthday?.let(dateFormatter::parse),
weight = requireNotNull(weight),
height = requireNotNull(height?.toInt()),
ptPurpose = goalContents,
caution = cautionNote,
birthday = trainee?.birthday?.let(dateFormatter::parse),
weight = requireNotNull(trainee?.weight),
height = requireNotNull(trainee?.height?.toInt()),
ptPurpose = trainee?.ptGoals ?: emptyList(),
caution = trainee?.cautionNote,
isConnected = false,
)

MemberType.UNREGISTERED -> error("등록되지 않은 유저입니다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package co.kr.data.repository

import co.kr.data.network.model.toDomain
import co.kr.data.network.model.trainee.DailyRecordsResponse
import co.kr.data.network.model.trainee.MonthlyRecordedDatesResponse
import co.kr.data.network.model.trainee.PtSessionResponse
import co.kr.data.network.model.trainee.RecordResponse
import co.kr.data.network.model.trainee.RecordedDateResponse
import co.kr.data.network.model.trainee.toDomain
import co.kr.data.network.source.UserRemoteDataSource
import co.kr.tnt.domain.model.User
import co.kr.tnt.domain.model.trainee.TraineeDailyRecord
import co.kr.tnt.domain.model.trainee.TraineeDailyRecordStatus
import co.kr.tnt.domain.repository.TraineeRepository
Expand All @@ -17,8 +20,15 @@ import javax.inject.Singleton

@Singleton
internal class TraineeRepositoryImpl @Inject constructor(
private val userRemoteDataSource: UserRemoteDataSource,
private val dateFormatter: DateFormatter,
) : TraineeRepository {
override suspend fun getMyInfo(): User.Trainee {
val user = userRemoteDataSource.getMyInfo().toDomain(dateFormatter)
require(user is User.Trainee)
return user
}

// TODO : API에 맞춰 수정
override suspend fun getDailyDataStatus(yearMonth: YearMonth): List<TraineeDailyRecordStatus> {
val result = MonthlyRecordedDatesResponse(
Expand All @@ -36,6 +46,7 @@ internal class TraineeRepositoryImpl @Inject constructor(
return result
}

// TODO : API에 맞춰 수정
override suspend fun getTraineeDailyRecord(day: LocalDate): TraineeDailyRecord {
val result = listOf(
DailyRecordsResponse(
Expand Down
2 changes: 2 additions & 0 deletions domain/src/main/java/co/kr/tnt/domain/model/User.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sealed class User {
val height: Int,
val ptPurpose: List<String>,
val caution: String?,
val isConnected: Boolean,
) : User() {
/** 한국식 나이 */
val age: Int? =
Expand All @@ -49,6 +50,7 @@ sealed class User {
height = 0,
ptPurpose = emptyList(),
caution = null,
isConnected = false,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package co.kr.tnt.domain.repository

import co.kr.tnt.domain.model.User
import co.kr.tnt.domain.model.trainee.TraineeDailyRecord
import co.kr.tnt.domain.model.trainee.TraineeDailyRecordStatus
import java.time.LocalDate
import java.time.YearMonth

interface TraineeRepository {
suspend fun getMyInfo(): User.Trainee
suspend fun getDailyDataStatus(yearMonth: YearMonth): List<TraineeDailyRecordStatus>

suspend fun getTraineeDailyRecord(day: LocalDate): TraineeDailyRecord
}
2 changes: 1 addition & 1 deletion feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fun TnTNavHost(
navigateToLogin = { navController.navigateToLogin(clearBackStack = true) },
)
traineeMainScreen(
navigateToConnect = { navController.navigateToTraineeConnect(true) },
navigateToConnect = navController::navigateToTraineeConnect,
navigateToWebView = navController::navigateToWebView,
navigateToLogin = { navController.navigateToLogin(clearBackStack = true) },
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import co.kr.tnt.trainee.notification.navigation.traineeNotification

@Composable
internal fun TraineeMainRoute(
navigateToConnect: () -> Unit,
navigateToConnect: (Boolean) -> Unit,
navigateToLogin: () -> Unit,
navigateToWebView: (url: String) -> Unit,
) {
Expand All @@ -37,7 +37,7 @@ internal fun TraineeMainRoute(
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
private fun TraineeMainScreen(
state: TraineeMainState,
navigateToConnect: () -> Unit,
navigateToConnect: (Boolean) -> Unit,
navigateToLogin: () -> Unit,
navigateToWebView: (url: String) -> Unit,
) {
Expand Down Expand Up @@ -70,7 +70,6 @@ private fun TraineeMainScreen(
)
}
traineeMyPageNavGraph(
navigateToPrevious = navController::popBackStack,
navigateToLogin = navigateToLogin,
navigateToWebView = navigateToWebView,
navigateToTraineeConnect = navigateToConnect,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fun NavController.navigateToTraineeMain(
)

fun NavGraphBuilder.traineeMainScreen(
navigateToConnect: () -> Unit,
navigateToConnect: (Boolean) -> Unit,
navigateToLogin: () -> Unit,
navigateToWebView: (url: String) -> Unit,
) {
Expand Down
4 changes: 4 additions & 0 deletions feature/trainee/mypage/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ android {
}

dependencies {
implementation(projects.core.login)

implementation(libs.kotlinx.immutable)
implementation(libs.accompanist.permissions)
implementation(libs.play.services.oss.licenses)
}
Original file line number Diff line number Diff line change
@@ -1,45 +1,49 @@
package co.kr.tnt.trainee.mypage

import co.kr.tnt.trainee.mypage.model.DialogState
import co.kr.tnt.domain.model.User
import co.kr.tnt.ui.base.UiEvent
import co.kr.tnt.ui.base.UiSideEffect
import co.kr.tnt.ui.base.UiState

internal class TraineeMyPageContract {
data class TraineeMyPageUiState(
val image: String? = "",
val name: String = "",
val user: User.Trainee = User.Trainee.EMPTY,
val trainerName: String = "",
val isConnected: Boolean = false,
val isPushEnabled: Boolean = true,
val appVersion: String = "0.0.0",
val dialogState: DialogState = DialogState.LOGOUT,
val url: String = "",
val showWebView: Boolean = false,
val showWarningDialog: Boolean = false,
val showCompleteDialog: Boolean = false,
) : UiState
val isEnablePushNotification: Boolean = true,
val dialogState: DialogState = DialogState.NONE,
) : UiState {
enum class DialogState {
NONE,
LOGOUT_CONFIRM,
LOGOUT,
DELETE_ACCOUNT_CONFIRM,
DELETE_ACCOUNT,
SHOULD_ALLOW_PERMISSION,
}
}

sealed interface TraineeMyPageUiEvent : UiEvent {
data object OnEditButtonClick : TraineeMyPageUiEvent
data object OnConnectButtonClick : TraineeMyPageUiEvent
data object OnDisconnectButtonClick : TraineeMyPageUiEvent
data object ToggleNotification : TraineeMyPageUiEvent
data object OnServiceTermClick : TraineeMyPageUiEvent
data object OnPrivacyClick : TraineeMyPageUiEvent
data object OnOpenSourceClick : TraineeMyPageUiEvent
data object OnLogoutClick : TraineeMyPageUiEvent
data object OnDeleteAccountClick : TraineeMyPageUiEvent
data object OnConfirmWarningDialog : TraineeMyPageUiEvent
data object OnConfirmCompleteDialog : TraineeMyPageUiEvent
data object OnDismissPopup : TraineeMyPageUiEvent
data class OnToggleNotification(
val isGrantedPermission: Boolean,
val shouldShowRationale: Boolean,
) : TraineeMyPageUiEvent

data object OnClickConnect : TraineeMyPageUiEvent
data object OnClickTermsOfService : TraineeMyPageUiEvent
data object OnClickPrivacy : TraineeMyPageUiEvent
data object OnClickOpenSource : TraineeMyPageUiEvent
data object OnClickLogout : TraineeMyPageUiEvent
data object OnClickDeleteAccount : TraineeMyPageUiEvent
data object OnClickDialogConfirm : TraineeMyPageUiEvent
data object OnDismissDialog : TraineeMyPageUiEvent
}

sealed interface TraineeMyPageEffect : UiSideEffect {
data class ShowToast(val message: String) : TraineeMyPageEffect
data object NavigateToConnect : TraineeMyPageEffect
data object NavigateToPrevious : TraineeMyPageEffect
data object NavigateToLogin : TraineeMyPageEffect
data class NavigateToWebView(val url: String) : TraineeMyPageEffect
data object NavigateToOpenSourceLicense : TraineeMyPageEffect
data class RequestPermission(val isExplicitlyDenied: Boolean) : TraineeMyPageEffect
}
}
Loading