diff --git a/core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/dropdown/SolplyBasicDropDown.kt b/core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/dropdown/SolplyBasicDropDown.kt index 8f732d6d..fbf5cdc8 100644 --- a/core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/dropdown/SolplyBasicDropDown.kt +++ b/core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/dropdown/SolplyBasicDropDown.kt @@ -34,7 +34,7 @@ fun SolplyBasicDropDown( onClickDropIcon: () -> Unit, modifier: Modifier = Modifier, isDropped: Boolean = false, - content: @Composable ColumnScope.() -> Unit, + content: @Composable ColumnScope.() -> Unit ) { Column( modifier = modifier @@ -100,4 +100,4 @@ fun SolplyBasicDropDown( } } } -} \ No newline at end of file +} diff --git a/core/model/src/main/java/com/teamsolply/solply/model/Persona.kt b/core/model/src/main/java/com/teamsolply/solply/model/Persona.kt new file mode 100644 index 00000000..d2a0de13 --- /dev/null +++ b/core/model/src/main/java/com/teamsolply/solply/model/Persona.kt @@ -0,0 +1,12 @@ +package com.teamsolply.solply.model + +import kotlinx.serialization.Serializable + +@Serializable +enum class Persona(val description: String) { + REST("조용한 공간에 오래 머물고 싶어요"), + EXPLORER("이곳저곳 둘러보고 싶어요"), + MOODING("취향이 담긴 곳을 찾고 싶어요"), + NATURAL("자연을 감상하며 쉬고 싶어요"), + ANYTHING("특별히 선호하는 공간은 없어요") +} diff --git a/data/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSource.kt b/data/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSource.kt index 4b07212c..3d18a557 100644 --- a/data/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSource.kt +++ b/data/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSource.kt @@ -1,3 +1,13 @@ package com.teamsolply.solply.mypage.datasource -interface MypageRemoteDataSource +import com.teamsolply.solply.mypage.dto.response.GetPersonaListResponseDto +import com.teamsolply.solply.mypage.dto.response.GetUserInfoResponseDto +import com.teamsolply.solply.mypage.dto.response.NicknameDuplicateResponseDto +import com.teamsolply.solply.mypage.dto.response.PlaceListResponseDto + +interface MypageRemoteDataSource { + suspend fun getUserInfo(): GetUserInfoResponseDto + suspend fun getPlaceList(townId: Long): PlaceListResponseDto + suspend fun getPersonaList(): GetPersonaListResponseDto + suspend fun checkNicknameDuplicate(nickname: String): NicknameDuplicateResponseDto +} diff --git a/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/GetPersonaListResponseDto.kt b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/GetPersonaListResponseDto.kt new file mode 100644 index 00000000..fc41fce3 --- /dev/null +++ b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/GetPersonaListResponseDto.kt @@ -0,0 +1,19 @@ +package com.teamsolply.solply.mypage.dto.response + +import com.teamsolply.solply.model.Persona +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class GetPersonaListResponseDto( + @SerialName("personaList") + val personaDtoList: List +) + +@Serializable +data class PersonaDto( + @SerialName("personaType") + val personaType: Persona, + @SerialName("description") + val description: String +) diff --git a/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/GetUserInfoResponseDto.kt b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/GetUserInfoResponseDto.kt new file mode 100644 index 00000000..a0fb06fa --- /dev/null +++ b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/GetUserInfoResponseDto.kt @@ -0,0 +1,41 @@ +package com.teamsolply.solply.mypage.dto.response + +import com.teamsolply.solply.model.Persona +import com.teamsolply.solply.mypage.model.SelectedTownInfo +import com.teamsolply.solply.mypage.model.UserInfo +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class GetUserInfoResponseDto( + @SerialName("userId") + val userId: Long, + @SerialName("nickname") + val nickname: String, + @SerialName("selectedTown") + val selectedTown: SelectedTownDto, + @SerialName("persona") + val persona: Persona, + @SerialName("profileImageUrl") + val profileImageUrl: String? +) + +@Serializable +data class SelectedTownDto( + @SerialName("townId") + val townId: Long, + @SerialName("townName") + val townName: String +) + +fun GetUserInfoResponseDto.toDomain(): UserInfo = + UserInfo( + userId = userId, + nickname = nickname, + selectedTown = SelectedTownInfo( + townId = selectedTown.townId, + townName = selectedTown.townName + ), + persona = persona, + profileImageUrl = profileImageUrl ?: "" // 서버 null → 도메인 기본값 + ) diff --git a/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/NicknameDuplicateResponseDto.kt b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/NicknameDuplicateResponseDto.kt new file mode 100644 index 00000000..10157839 --- /dev/null +++ b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/NicknameDuplicateResponseDto.kt @@ -0,0 +1,10 @@ +package com.teamsolply.solply.mypage.dto.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class NicknameDuplicateResponseDto( + @SerialName("isDuplicated") + val isDuplicated: Boolean +) diff --git a/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/PlaceListResponseDto.kt b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/PlaceListResponseDto.kt new file mode 100644 index 00000000..a9d1cf92 --- /dev/null +++ b/data/mypage/src/main/java/com/teamsolply/solply/mypage/dto/response/PlaceListResponseDto.kt @@ -0,0 +1,30 @@ +package com.teamsolply.solply.mypage.dto.response + +import com.teamsolply.solply.model.PlaceType +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class PlaceListResponseDto( + + @SerialName("places") + val placeList: List +) + +@Serializable +data class PlaceResponseDto( + @SerialName("placeId") + val placeId: Long, + + @SerialName("placeName") + val placeName: String, + + @SerialName("thumbnailImageUrl") + val imageUrl: String, + + @SerialName("primaryTag") + val tag: PlaceType, + + @SerialName("isBookmarked") + val isSaved: Boolean +) diff --git a/data/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepositoryImpl.kt b/data/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepositoryImpl.kt index 68ada57a..b828e137 100644 --- a/data/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepositoryImpl.kt +++ b/data/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepositoryImpl.kt @@ -1,8 +1,49 @@ package com.teamsolply.solply.mypage.repository +import android.util.Log import com.teamsolply.solply.mypage.datasource.MypageRemoteDataSource +import com.teamsolply.solply.mypage.dto.response.toDomain +import com.teamsolply.solply.mypage.model.PersonaEntity +import com.teamsolply.solply.mypage.model.PlaceInfoEntity +import com.teamsolply.solply.mypage.model.UserInfo import javax.inject.Inject class MypageRepositoryImpl @Inject constructor( private val mypageRemoteDataSource: MypageRemoteDataSource -) : MypageRepository +) : MypageRepository { + override suspend fun getUserInfo(): Result = runCatching { + mypageRemoteDataSource.getUserInfo() + }.mapCatching { userDto -> + userDto.toDomain() + } + + override suspend fun getPlaceList(townId: Long): Result> = runCatching { + mypageRemoteDataSource.getPlaceList(townId).placeList + }.mapCatching { placeList -> + placeList.map { place -> + PlaceInfoEntity( + placeId = place.placeId, + placeName = place.placeName, + placeType = place.tag, + imageUrls = place.imageUrl, + isSaved = place.isSaved + ) + } + } + + override suspend fun getPersonaList(): Result> = runCatching { + mypageRemoteDataSource.getPersonaList().personaDtoList + }.mapCatching { personaList -> + Log.d("persona: ", "repo impl start") + personaList.map { persona -> + PersonaEntity( + personaType = persona.personaType, + description = persona.description + ) + } + } + + override suspend fun checkNicknameDuplicate(nickname: String): Result = runCatching { + mypageRemoteDataSource.checkNicknameDuplicate(nickname = nickname).isDuplicated + } +} diff --git a/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/PersonaEntity.kt b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/PersonaEntity.kt new file mode 100644 index 00000000..aff00551 --- /dev/null +++ b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/PersonaEntity.kt @@ -0,0 +1,8 @@ +package com.teamsolply.solply.mypage.model + +import com.teamsolply.solply.model.Persona + +data class PersonaEntity( + val personaType: Persona, + val description: String +) diff --git a/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/PlaceInfoEntity.kt b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/PlaceInfoEntity.kt new file mode 100644 index 00000000..d391c0cc --- /dev/null +++ b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/PlaceInfoEntity.kt @@ -0,0 +1,12 @@ +package com.teamsolply.solply.mypage.model + +import com.teamsolply.solply.model.PlaceType + +data class PlaceInfoEntity( + val placeId: Long, + val placeName: String, + val placeType: PlaceType, + val imageUrls: String, + val isSaved: Boolean, + val isSelected: Boolean = false +) diff --git a/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/UserInfo.kt b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/UserInfo.kt new file mode 100644 index 00000000..60379bfa --- /dev/null +++ b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/model/UserInfo.kt @@ -0,0 +1,16 @@ +package com.teamsolply.solply.mypage.model + +import com.teamsolply.solply.model.Persona + +data class UserInfo( + val userId: Long, + val nickname: String, + val selectedTown: SelectedTownInfo, + val persona: Persona, + val profileImageUrl: String = "" +) + +data class SelectedTownInfo( + val townId: Long, + val townName: String +) diff --git a/domain/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepository.kt b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepository.kt index bcab9603..86b7648a 100644 --- a/domain/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepository.kt +++ b/domain/mypage/src/main/java/com/teamsolply/solply/mypage/repository/MypageRepository.kt @@ -1,3 +1,12 @@ package com.teamsolply.solply.mypage.repository -interface MypageRepository +import com.teamsolply.solply.mypage.model.PersonaEntity +import com.teamsolply.solply.mypage.model.PlaceInfoEntity +import com.teamsolply.solply.mypage.model.UserInfo + +interface MypageRepository { + suspend fun getUserInfo(): Result + suspend fun getPlaceList(townId: Long): Result> + suspend fun getPersonaList(): Result> + suspend fun checkNicknameDuplicate(nickname: String): Result +} diff --git a/feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt b/feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt index 394a55fb..3c1522d7 100644 --- a/feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt +++ b/feature/main/src/main/java/com/teamsolply/solply/main/MainScreen.kt @@ -41,7 +41,6 @@ import com.teamsolply.solply.maps.navigation.mapsNavGraph import com.teamsolply.solply.model.SnackBarType import com.teamsolply.solply.mypage.navigation.Mypage import com.teamsolply.solply.mypage.navigation.mypageNavGraph -import com.teamsolply.solply.mypage.profile.navigation.Profile import com.teamsolply.solply.mypage.profile.navigation.profileNavGraph import com.teamsolply.solply.oauth.navigation.oauthNavGraph import com.teamsolply.solply.onboarding.navigation.onBoardingNavGraph diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt index a8cdbe30..bdeca22e 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageContract.kt @@ -1,22 +1,38 @@ package com.teamsolply.solply.mypage -import com.teamsolply.solply.mypage.model.DropDownPersonaItem +import com.teamsolply.solply.model.Persona +import com.teamsolply.solply.mypage.model.PlaceInfoEntity +import com.teamsolply.solply.mypage.model.SelectedTownInfo +import com.teamsolply.solply.mypage.model.UserInfo import com.teamsolply.solply.ui.base.SideEffect import com.teamsolply.solply.ui.base.UiIntent import com.teamsolply.solply.ui.base.UiState -import kotlinx.collections.immutable.persistentListOf data class MypageState( - val town: String = "연희동", - val nickname: String = "", + val userInfo: UserInfo = UserInfo( + userId = 1, + nickname = "숭이숭이숭이", + selectedTown = SelectedTownInfo(0, "망원동"), + persona = Persona.REST, + profileImageUrl = "" + ), + val placeList: List = emptyList(), + val dialogState: Boolean = false ) : UiState sealed interface MypageIntent : UiIntent { + data object Init : MypageIntent + data object LogOutButtonClick : MypageIntent + data object WithdrawButtonClick : MypageIntent + + data object DialogConfirmClick : MypageIntent + data object DialogDismissClick : MypageIntent + + data object ProfileEditClick : MypageIntent } sealed interface MypageSideEffect : SideEffect { data object NavigateToBack : MypageSideEffect data object NavigateToProfile : MypageSideEffect - data object NavigateToMypage : MypageSideEffect } diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt index 94ee26f8..c6cbd419 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageScreen.kt @@ -16,19 +16,29 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.teamsolply.solply.designsystem.component.dialog.SolplyConfirmDialog import com.teamsolply.solply.designsystem.theme.SolplyTheme import com.teamsolply.solply.mypage.component.EmptyPlaceContainer import com.teamsolply.solply.mypage.component.MypageSettingItem +import com.teamsolply.solply.mypage.component.SavedPlaceListContainer +import com.teamsolply.solply.mypage.model.PlaceInfoEntity import com.teamsolply.solply.ui.extension.customClickable +import com.teamsolply.solply.ui.lifecycle.LaunchedEffectWithLifecycle +import kotlinx.coroutines.flow.collectLatest @Composable fun MypageRoute( @@ -37,19 +47,55 @@ fun MypageRoute( navigateToProfile: () -> Unit, viewModel: MypageViewModel = hiltViewModel() ) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + LaunchedEffect(Unit) { + viewModel.sendIntent(MypageIntent.Init) + } + + LaunchedEffectWithLifecycle { + viewModel.sideEffect.collectLatest { sideEffect -> + when (sideEffect) { + MypageSideEffect.NavigateToBack -> navigateToBack() + MypageSideEffect.NavigateToProfile -> navigateToProfile() + } + } + } + MypageScreen( + nickname = uiState.userInfo.nickname, + savedPlaceList = uiState.placeList, + dialogState = uiState.dialogState, onBackButtonClick = navigateToBack, - onProfileEditClick = navigateToProfile, - modifier = Modifier.padding(paddingValues), + onProfileEditClick = { viewModel.sendIntent(MypageIntent.ProfileEditClick) }, + onLogOutClick = { viewModel.sendIntent(MypageIntent.LogOutButtonClick) }, + onDialogConfirmClick = { viewModel.sendIntent(MypageIntent.DialogConfirmClick) }, + onDialogDismissClick = { viewModel.sendIntent(MypageIntent.DialogDismissClick) }, + modifier = Modifier.padding(paddingValues) ) } @Composable fun MypageScreen( + nickname: String, + savedPlaceList: List, + dialogState: Boolean, onBackButtonClick: () -> Unit, onProfileEditClick: () -> Unit, + onLogOutClick: () -> Unit, + onDialogConfirmClick: () -> Unit, + onDialogDismissClick: () -> Unit, modifier: Modifier = Modifier ) { + if (dialogState) { + SolplyConfirmDialog( + text = stringResource(R.string.logout_dialog), + confirmButtonText = stringResource(R.string.logout_dialog_confirm), + dismissButtonText = stringResource(R.string.mypage_dialog_cancel), + onClickConfirm = onDialogConfirmClick, + onClickDismiss = onDialogDismissClick + ) + } Column( modifier .fillMaxSize() @@ -83,22 +129,35 @@ fun MypageScreen( ) Spacer(modifier = Modifier.height(12.dp)) Text( - text = "닉네임", + text = nickname, color = SolplyTheme.colors.black, - style = SolplyTheme.typography.display20Sb + style = SolplyTheme.typography.display20Sb.copy( + lineHeightStyle = LineHeightStyle( + alignment = LineHeightStyle.Alignment.Center, + trim = LineHeightStyle.Trim.None + ) + ) ) + Spacer(modifier = Modifier.height(12.dp)) Row( modifier = Modifier - .padding(top = 12.dp) .customClickable( rippleEnabled = false, onClick = onProfileEditClick - ) + ), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically ) { Text( - text = "프로필 수정", + text = stringResource(R.string.profile_edit), color = SolplyTheme.colors.gray600, - style = SolplyTheme.typography.button14M + style = SolplyTheme.typography.button14M, + modifier = Modifier.padding(start = 16.dp) + ) + Icon( + painter = painterResource(com.teamsolply.solply.designsystem.R.drawable.ic_next_arrow), + contentDescription = "", + tint = SolplyTheme.colors.gray600 ) } Spacer(modifier = Modifier.height(44.dp)) @@ -120,7 +179,19 @@ fun MypageScreen( style = SolplyTheme.typography.body16M ) } - EmptyPlaceContainer() + if (savedPlaceList.isEmpty()) { + EmptyPlaceContainer( + modifier = Modifier + .padding(bottom = 16.dp) + ) + } else { + SavedPlaceListContainer( + savedPlaceList = savedPlaceList, + modifier = Modifier + .fillMaxWidth() + .padding(start = 20.dp, bottom = 16.dp) + ) + } } Spacer(modifier = Modifier.height(16.dp)) Column( @@ -136,13 +207,13 @@ fun MypageScreen( .padding(top = 16.dp, start = 20.dp, end = 16.dp, bottom = 12.dp) ) { Text( - text = "계정 설정", + text = stringResource(R.string.mypage_account_setting), color = SolplyTheme.colors.black, style = SolplyTheme.typography.body16M ) } MypageSettingItem( - text = "고객센터", + text = stringResource(R.string.mypage_customer_service), onClick = { /* TODO */ }, isBorderEnabled = true ) @@ -159,8 +230,8 @@ fun MypageScreen( isBorderEnabled = true ) MypageSettingItem( - text = "로그아웃", - onClick = { /* TODO */ }, + text = stringResource(R.string.mypage_logout), + onClick = onLogOutClick, isBorderEnabled = true ) MypageSettingItem( @@ -168,10 +239,8 @@ fun MypageScreen( onClick = { /* TODO */ }, isBorderEnabled = false ) + Spacer(modifier = Modifier.height(8.dp)) } - Spacer( - modifier = Modifier.weight(36f) - ) } } @@ -180,8 +249,14 @@ fun MypageScreen( private fun MypageScreenPreview() { SolplyTheme { MypageScreen( + nickname = "닉네임", + savedPlaceList = emptyList(), + dialogState = false, onBackButtonClick = {}, - onProfileEditClick = {} + onProfileEditClick = {}, + onLogOutClick = {}, + onDialogConfirmClick = {}, + onDialogDismissClick = {} ) } } diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageViewModel.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageViewModel.kt index 1884a3a1..024b3409 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageViewModel.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/MypageViewModel.kt @@ -1,8 +1,11 @@ package com.teamsolply.solply.mypage +import androidx.lifecycle.viewModelScope import com.teamsolply.solply.mypage.repository.MypageRepository import com.teamsolply.solply.ui.base.BaseViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -11,6 +14,61 @@ class MypageViewModel @Inject constructor( ) : BaseViewModel(MypageState()) { override fun handleIntent(intent: MypageIntent) { - TODO("Not yet implemented") + when (intent) { + MypageIntent.Init -> getInitInfo() + + MypageIntent.LogOutButtonClick -> { + reduce { + copy( + dialogState = true + ) + } + } + + MypageIntent.WithdrawButtonClick -> { + } + + MypageIntent.DialogConfirmClick -> { + // TODO 로그아웃 api + reduce { + copy(dialogState = false) + } + } + + MypageIntent.DialogDismissClick -> { + reduce { + copy(dialogState = false) + } + } + + MypageIntent.ProfileEditClick -> { + postSideEffect(MypageSideEffect.NavigateToProfile) + } + } + } + + private fun getInitInfo() { + viewModelScope.launch { + mypageRepository.getUserInfo() + .onSuccess { userInfo -> + reduce { copy(userInfo = userInfo) } + + getPlaceList( + townId = userInfo.selectedTown.townId + ) + } + } + } + + private fun getPlaceList(townId: Long) { + viewModelScope.launch { + mypageRepository.getPlaceList(townId).onSuccess { + reduce { + copy( + placeList = it.toPersistentList() + ) + } + } + } } } diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/EmptyPlaceContainer.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/EmptyPlaceContainer.kt index 270abe9d..a1e24f02 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/EmptyPlaceContainer.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/EmptyPlaceContainer.kt @@ -3,7 +3,6 @@ package com.teamsolply.solply.mypage.component import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -17,7 +16,6 @@ fun EmptyPlaceContainer( ) { Box( modifier = modifier - .padding(bottom = 16.dp) .height(40.dp) .fillMaxWidth(), contentAlignment = Alignment.Center diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/MypageSettingItem.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/MypageSettingItem.kt index 366d9893..59b1aaeb 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/MypageSettingItem.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/MypageSettingItem.kt @@ -12,6 +12,7 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.Offset import androidx.compose.ui.unit.dp import com.teamsolply.solply.designsystem.theme.SolplyTheme +import com.teamsolply.solply.ui.extension.customClickable @Composable fun MypageSettingItem( @@ -41,6 +42,10 @@ fun MypageSettingItem( } else { Modifier } + ) + .customClickable( + rippleEnabled = false, + onClick = onClick ), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = if (info.isNotEmpty()) { diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SavedPlaceListContainer.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SavedPlaceListContainer.kt new file mode 100644 index 00000000..1ecfdcbd --- /dev/null +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SavedPlaceListContainer.kt @@ -0,0 +1,46 @@ +package com.teamsolply.solply.mypage.component + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.teamsolply.solply.designsystem.component.card.SolplyPlaceCard +import com.teamsolply.solply.designsystem.theme.SolplyTheme +import com.teamsolply.solply.mypage.model.PlaceInfoEntity + +@Composable +fun SavedPlaceListContainer( + savedPlaceList: List, + modifier: Modifier = Modifier +) { + LazyRow( + modifier = modifier + .fillMaxWidth() + ) { + items(savedPlaceList) { + SolplyPlaceCard( + name = it.placeName, + placeType = it.placeType, + imgRes = it.imageUrls, + selected = it.isSelected, + saved = it.isSaved, + touchable = false, + modifier = Modifier.size(height = 165.dp, width = 136.dp) + ) + } + } +} + +@Preview +@Composable +private fun SavedPlaceListContainerPreview() { + SolplyTheme { + SavedPlaceListContainer( + savedPlaceList = emptyList() + ) + } +} diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt index 00046180..1c4f894f 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/component/SolplyPersonaDropDown.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.teamsolply.solply.designsystem.component.dropdown.SolplyBasicDropDown import com.teamsolply.solply.designsystem.theme.SolplyTheme -import com.teamsolply.solply.mypage.model.DropDownPersonaItem +import com.teamsolply.solply.mypage.model.PersonaEntity import com.teamsolply.solply.ui.extension.customClickable import kotlinx.collections.immutable.persistentListOf @@ -29,14 +29,14 @@ fun SolplyPersonaDropDown( placeholder: String, onClickItem: (Int) -> Unit, onClickDropIcon: () -> Unit, - dropDownContents: List, + dropDownContents: List, selectedIndex: Int, modifier: Modifier = Modifier, isDropped: Boolean = false, isSelected: Boolean = false ) { SolplyBasicDropDown( - defaultLabel = if (isSelected) dropDownContents.get(selectedIndex).label else placeholder, + defaultLabel = if (isSelected) dropDownContents[selectedIndex].description else placeholder, onClickDropIcon = onClickDropIcon, isDropped = isDropped, modifier = modifier @@ -57,7 +57,7 @@ fun SolplyPersonaDropDown( horizontalArrangement = Arrangement.Start ) { Text( - text = item.label, + text = item.description, color = SolplyTheme.colors.gray900, style = SolplyTheme.typography.body16M, modifier = Modifier.padding( @@ -89,20 +89,7 @@ private fun SolplyPersonaDropDownPreview() { placeholder = "조용한 공간에 오래 머물고 싶어요", onClickItem = {}, onClickDropIcon = {}, - dropDownContents = persistentListOf( - DropDownPersonaItem( - "이곳저곳 둘러보고 싶어요" - ), - DropDownPersonaItem( - "취향이 담긴 곳을 찾고 싶어요" - ), - DropDownPersonaItem( - "자연을 감상하며 쉬고 싶어요" - ), - DropDownPersonaItem( - "조용한 공간에 오래 머물고 싶어요" - ), - ), + dropDownContents = persistentListOf(), isDropped = false, selectedIndex = 0, isSelected = false @@ -115,23 +102,10 @@ private fun SolplyPersonaDropDownPreview() { isSelected = true }, onClickDropIcon = { isDropped = !isDropped }, - dropDownContents = persistentListOf( - DropDownPersonaItem( - "이곳저곳 둘러보고 싶어요" - ), - DropDownPersonaItem( - "취향이 담긴 곳을 찾고 싶어요" - ), - DropDownPersonaItem( - "자연을 감상하며 쉬고 싶어요" - ), - DropDownPersonaItem( - "조용한 공간에 오래 머물고 싶어요" - ), - ), + dropDownContents = persistentListOf(), selectedIndex = selectedIndex, isSelected = isSelected ) } } -} \ No newline at end of file +} diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt index 8937319c..b272060d 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/navigation/MypageNavigation.kt @@ -20,7 +20,7 @@ fun NavController.navigateMypage( fun NavGraphBuilder.mypageNavGraph( navigateToBack: () -> Unit, navigateToProfile: () -> Unit, - paddingValues: PaddingValues, + paddingValues: PaddingValues ) { composable { backStackEntry -> val viewModel: MypageViewModel = hiltViewModel(backStackEntry) diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditContract.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditContract.kt new file mode 100644 index 00000000..6f45d38e --- /dev/null +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditContract.kt @@ -0,0 +1,48 @@ +package com.teamsolply.solply.mypage.profile + +import com.teamsolply.solply.model.Persona +import com.teamsolply.solply.mypage.model.PersonaEntity +import com.teamsolply.solply.mypage.model.SelectedTownInfo +import com.teamsolply.solply.mypage.model.UserInfo +import com.teamsolply.solply.ui.base.SideEffect +import com.teamsolply.solply.ui.base.UiIntent +import com.teamsolply.solply.ui.base.UiState + +data class ProfileEditState( + val userInfo: UserInfo = UserInfo( + userId = 1, + nickname = "숭이숭이숭이", + selectedTown = SelectedTownInfo(0, "망원동"), + persona = Persona.REST, + profileImageUrl = "" + ), + val inputNickname: String = "", + val isNicknameDuplicate: Boolean = false, + val isEditSuccess: Boolean = false, + val personaList: List = emptyList(), + val selectedPersonaIndex: Int = -1, + val isDropped: Boolean = false, + val completeButtonEnabled: Boolean = false, + val dialogState: Boolean = false +) : UiState + +sealed interface ProfileEditIntent : UiIntent { + data object Init : ProfileEditIntent + + data class ChangeInputNickname(val nickname: String) : ProfileEditIntent + data object ValidateNickname : ProfileEditIntent + data class ChangeEditingSuccess(val state: Boolean) : ProfileEditIntent + + data object DropDownIconClick : ProfileEditIntent + data class DropDownItemClick(val index: Int) : ProfileEditIntent + data object CompleteButtonClick : ProfileEditIntent + data object BackButtonClick : ProfileEditIntent + + data object DialogConfirmClick : ProfileEditIntent + data object DialogDismissClick : ProfileEditIntent +} + +sealed interface ProfileEditSideEffect : SideEffect { + data object NavigateToBack : ProfileEditSideEffect + data object NavigateToMypage : ProfileEditSideEffect +} diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt similarity index 50% rename from feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt rename to feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt index 4fd3841e..8208519a 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileScreen.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditScreen.kt @@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -24,35 +26,94 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.teamsolply.solply.designsystem.component.button.SolplyBasicButton +import com.teamsolply.solply.designsystem.component.dialog.SolplyConfirmDialog import com.teamsolply.solply.designsystem.component.textfield.SolplyNicknameTextField import com.teamsolply.solply.designsystem.component.topbar.SolplyTopBar import com.teamsolply.solply.designsystem.theme.SolplyTheme -import com.teamsolply.solply.mypage.MypageViewModel import com.teamsolply.solply.mypage.R import com.teamsolply.solply.mypage.component.SolplyPersonaDropDown +import com.teamsolply.solply.mypage.model.PersonaEntity +import com.teamsolply.solply.ui.lifecycle.LaunchedEffectWithLifecycle import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.collectLatest @Composable fun ProfileRoute( paddingValues: PaddingValues, navigateToBack: () -> Unit, navigateToMypage: () -> Unit, - viewModel: MypageViewModel = hiltViewModel() + viewModel: ProfileEditViewModel = hiltViewModel() ) { - ProfileScreen( - onBackButtonClick = navigateToBack, - onCompleteButtonClick = navigateToMypage, - modifier = Modifier.padding(paddingValues), + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + LaunchedEffect(Unit) { + viewModel.sendIntent(ProfileEditIntent.Init) + } + + LaunchedEffectWithLifecycle { + viewModel.sideEffect.collectLatest { sideEffect -> + when (sideEffect) { + ProfileEditSideEffect.NavigateToMypage -> { + navigateToMypage() + } + + ProfileEditSideEffect.NavigateToBack -> { + navigateToBack() + } + } + } + } + + ProfileEditScreen( + nickname = uiState.inputNickname, + isNicknameDuplicated = uiState.isNicknameDuplicate, + selectedPersonaIndex = uiState.selectedPersonaIndex, + personaList = uiState.personaList, + dialogState = uiState.dialogState, + isDropped = uiState.isDropped, + isEditSuccess = uiState.isEditSuccess, + onNicknameChanged = { viewModel.sendIntent(ProfileEditIntent.ChangeInputNickname(it)) }, + onNicknameValidateChanged = { viewModel.sendIntent(ProfileEditIntent.ChangeEditingSuccess(it)) }, + onDropIconClick = { viewModel.sendIntent(ProfileEditIntent.DropDownIconClick) }, + onDropDownItemClick = { viewModel.sendIntent(ProfileEditIntent.DropDownItemClick(it)) }, + onBackButtonClick = { viewModel.sendIntent(ProfileEditIntent.BackButtonClick) }, + onCompleteButtonClick = { viewModel.sendIntent(ProfileEditIntent.CompleteButtonClick) }, + onDialogConfirmClick = { viewModel.sendIntent(ProfileEditIntent.DialogConfirmClick) }, + onDialogDismissClick = { viewModel.sendIntent(ProfileEditIntent.DialogDismissClick) }, + modifier = Modifier.padding(paddingValues) ) } @Composable -fun ProfileScreen( +fun ProfileEditScreen( + nickname: String, + isNicknameDuplicated: Boolean, + selectedPersonaIndex: Int, + personaList: List, + dialogState: Boolean, + isDropped: Boolean, + isEditSuccess: Boolean, + onNicknameChanged: (String) -> Unit, + onNicknameValidateChanged: (Boolean) -> Unit, + onDropIconClick: () -> Unit, + onDropDownItemClick: (Int) -> Unit, onBackButtonClick: () -> Unit, onCompleteButtonClick: () -> Unit, + onDialogConfirmClick: () -> Unit, + onDialogDismissClick: () -> Unit, modifier: Modifier = Modifier ) { + if (dialogState) { + SolplyConfirmDialog( + text = stringResource(R.string.profile_dialog), + confirmButtonText = stringResource(R.string.profile_dialog_confirm), + dismissButtonText = stringResource(R.string.profile_dialog_cancel), + onClickConfirm = onDialogConfirmClick, + onClickDismiss = onDialogDismissClick + ) + } Column( modifier = modifier .fillMaxSize() @@ -94,11 +155,13 @@ fun ProfileScreen( ) } SolplyNicknameTextField( - value = "", - isNicknameDuplicate = false, - onValueChange = {}, - checkNicknameValidate = { true }, - changeNicknameValidate = {}, + value = nickname, + isNicknameDuplicate = isNicknameDuplicated, + onValueChange = onNicknameChanged, + changeNicknameValidate = onNicknameValidateChanged, + checkNicknameValidate = { input -> + input.all { it.isLetterOrDigit() } + }, modifier = Modifier.padding(top = 12.dp) ) } @@ -120,18 +183,27 @@ fun ProfileScreen( ) } SolplyPersonaDropDown( - placeholder = "선택해주세요.", - onClickItem = {}, - onClickDropIcon = {}, - dropDownContents = persistentListOf(), - selectedIndex = -1, + placeholder = stringResource(R.string.profile_persona_placeholder), + isDropped = isDropped, + onClickItem = onDropDownItemClick, + onClickDropIcon = onDropIconClick, + dropDownContents = personaList, + selectedIndex = selectedPersonaIndex, + isSelected = selectedPersonaIndex != -1, modifier = Modifier.padding(vertical = 12.dp) ) } Spacer(modifier = Modifier.weight(12f)) SolplyBasicButton( text = "완료", - onClick = {}, + selected = isEditSuccess, + onClick = { + if (isEditSuccess) { + onCompleteButtonClick() + } + }, + enabledBackgroundColor = SolplyTheme.colors.gray900, + disabledBackgroundColor = SolplyTheme.colors.gray300, modifier = Modifier.padding(vertical = 24.dp, horizontal = 16.dp) ) } @@ -141,9 +213,22 @@ fun ProfileScreen( @Composable private fun ProfileScreenPreview() { SolplyTheme { - ProfileScreen( + ProfileEditScreen( + nickname = "", + isNicknameDuplicated = false, + selectedPersonaIndex = -1, + personaList = persistentListOf(), + dialogState = false, + isDropped = false, + isEditSuccess = false, + onNicknameChanged = {}, + onNicknameValidateChanged = {}, + onDropIconClick = {}, + onDropDownItemClick = {}, onBackButtonClick = {}, - onCompleteButtonClick = {} + onCompleteButtonClick = {}, + onDialogConfirmClick = {}, + onDialogDismissClick = {} ) } } diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditViewModel.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditViewModel.kt new file mode 100644 index 00000000..1b47725b --- /dev/null +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/ProfileEditViewModel.kt @@ -0,0 +1,128 @@ +package com.teamsolply.solply.mypage.profile + +import android.util.Log +import androidx.lifecycle.viewModelScope +import com.teamsolply.solply.mypage.repository.MypageRepository +import com.teamsolply.solply.ui.base.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ProfileEditViewModel @Inject constructor( + private val mypageRepository: MypageRepository +) : + BaseViewModel(ProfileEditState()) { + private val nicknameFlow = MutableStateFlow("") + + override fun handleIntent(intent: ProfileEditIntent) { + when (intent) { + ProfileEditIntent.Init -> init() + + is ProfileEditIntent.ChangeInputNickname -> { + reduce { + copy(inputNickname = intent.nickname) + } + } + + ProfileEditIntent.ValidateNickname -> { + } + + ProfileEditIntent.BackButtonClick -> { + reduce { + copy(dialogState = true) + } + } + + is ProfileEditIntent.ChangeEditingSuccess -> { + reduce { + copy( + isEditSuccess = intent.state + ) + } + } + + ProfileEditIntent.DropDownIconClick -> { + reduce { + copy( + isDropped = !isDropped + ) + } + } + + is ProfileEditIntent.DropDownItemClick -> { + reduce { + copy( + selectedPersonaIndex = intent.index, + isDropped = !isDropped + ) + } + } + + ProfileEditIntent.CompleteButtonClick -> { + viewModelScope.launch { + // TODO 프로필 수정 patch api + postSideEffect( + ProfileEditSideEffect.NavigateToMypage + ) + } + } + + ProfileEditIntent.DialogConfirmClick -> { + viewModelScope.launch { + // TODO 로그아웃 api + postSideEffect( + ProfileEditSideEffect.NavigateToBack + ) + } + } + + ProfileEditIntent.DialogDismissClick -> { + reduce { + copy(dialogState = false) + } + } + } + } + + private fun init() { + viewModelScope.launch { + mypageRepository.getUserInfo() + .onSuccess { userInfo -> + reduce { + copy( + userInfo = userInfo, + inputNickname = userInfo.nickname + ) + } + } + .onFailure { + Log.i("getUser fail", "") + } + mypageRepository.getPersonaList() + .onSuccess { personaList -> + Log.d("persona: ", personaList.toString()) + reduce { copy(personaList = personaList) } + reduce { + val selectedIndex = + personaList.indexOfFirst { it.personaType == userInfo.persona } + copy(selectedPersonaIndex = selectedIndex) + } + } + nicknameFlow + .debounce(500) + .filter { it.isNotBlank() } + .collect { nickname -> + mypageRepository.checkNicknameDuplicate(nickname) + .onSuccess { isDuplicate -> + reduce { copy(isNicknameDuplicate = isDuplicate) } + }.onFailure { + reduce { copy(isNicknameDuplicate = false) } + } + } + } + } +} diff --git a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt index a6e4148e..bf0ac064 100644 --- a/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt +++ b/feature/mypage/src/main/java/com/teamsolply/solply/mypage/profile/navigation/ProfileNavigation.kt @@ -6,8 +6,7 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable -import com.teamsolply.solply.mypage.MypageRoute -import com.teamsolply.solply.mypage.MypageViewModel +import com.teamsolply.solply.mypage.profile.ProfileEditViewModel import com.teamsolply.solply.mypage.profile.ProfileRoute import com.teamsolply.solply.navigation.Route import kotlinx.serialization.Serializable @@ -21,10 +20,10 @@ fun NavController.navigateProfile( fun NavGraphBuilder.profileNavGraph( paddingValues: PaddingValues, navigateToBack: () -> Unit, - navigateToMypage: () -> Unit, + navigateToMypage: () -> Unit ) { composable { backStackEntry -> - val viewModel: MypageViewModel = hiltViewModel(backStackEntry) + val viewModel: ProfileEditViewModel = hiltViewModel(backStackEntry) ProfileRoute( paddingValues = paddingValues, navigateToBack = navigateToBack, @@ -35,4 +34,4 @@ fun NavGraphBuilder.profileNavGraph( } @Serializable -data object Profile : Route \ No newline at end of file +data object Profile : Route diff --git a/feature/mypage/src/main/res/values/strings.xml b/feature/mypage/src/main/res/values/strings.xml index 4bd40bea..7725f99c 100644 --- a/feature/mypage/src/main/res/values/strings.xml +++ b/feature/mypage/src/main/res/values/strings.xml @@ -1,7 +1,20 @@ + 계정 설정 + 고객센터 + 로그아웃 + 프로필 수정 기본 프로필 닉네임 나의 솔플 스타일 + 선택해주세요. + + 변경 사항을 저장하지 않고\n나가시겠어요? + 나가기 + 취소 + + 로그아웃하시겠습니까? + 취소 + 로그아웃 \ No newline at end of file diff --git a/remote/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSourceImpl.kt b/remote/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSourceImpl.kt index a19777cb..7cec758e 100644 --- a/remote/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSourceImpl.kt +++ b/remote/mypage/src/main/java/com/teamsolply/solply/mypage/datasource/MypageRemoteDataSourceImpl.kt @@ -1,8 +1,27 @@ package com.teamsolply.solply.mypage.datasource +import android.util.Log +import com.teamsolply.solply.mypage.dto.response.GetPersonaListResponseDto +import com.teamsolply.solply.mypage.dto.response.GetUserInfoResponseDto +import com.teamsolply.solply.mypage.dto.response.NicknameDuplicateResponseDto import com.teamsolply.solply.mypage.service.MypageService import javax.inject.Inject class MypageRemoteDataSourceImpl @Inject constructor( private val mypageService: MypageService -) : MypageRemoteDataSource +) : MypageRemoteDataSource { + override suspend fun getUserInfo(): GetUserInfoResponseDto { + val user = mypageService.getUserInfo().data + Log.d("getUser ", user.nickname) + return user + } + + override suspend fun getPlaceList(townId: Long) = + mypageService.getPlaceList(townId = townId).data + + override suspend fun getPersonaList(): GetPersonaListResponseDto = + mypageService.getPersonaList().data + + override suspend fun checkNicknameDuplicate(nickname: String): NicknameDuplicateResponseDto = + mypageService.checkNicknameDuplicate(nickname = nickname).data +} diff --git a/remote/mypage/src/main/java/com/teamsolply/solply/mypage/service/MypageService.kt b/remote/mypage/src/main/java/com/teamsolply/solply/mypage/service/MypageService.kt index 3d052ee7..ce98be63 100644 --- a/remote/mypage/src/main/java/com/teamsolply/solply/mypage/service/MypageService.kt +++ b/remote/mypage/src/main/java/com/teamsolply/solply/mypage/service/MypageService.kt @@ -1,3 +1,28 @@ package com.teamsolply.solply.mypage.service -interface MypageService +import com.teamsolply.solply.mypage.dto.response.GetPersonaListResponseDto +import com.teamsolply.solply.mypage.dto.response.GetUserInfoResponseDto +import com.teamsolply.solply.mypage.dto.response.NicknameDuplicateResponseDto +import com.teamsolply.solply.mypage.dto.response.PlaceListResponseDto +import com.teamsolply.solply.network.model.BaseResponse +import retrofit2.http.GET +import retrofit2.http.Query + +interface MypageService { + @GET("/api/users") + suspend fun getUserInfo(): BaseResponse + + @GET("api/places") + suspend fun getPlaceList( + @Query("townId") townId: Long, + @Query("isBookmarkSearch") isBookmarkedSearch: Boolean = true + ): BaseResponse + + @GET("api/users/persona") + suspend fun getPersonaList(): BaseResponse + + @GET("api/users/check-nickname") + suspend fun checkNicknameDuplicate( + @Query("nickname") nickname: String + ): BaseResponse +}