Skip to content

Commit

Permalink
#66 Feat : 닉네임 변경 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
DongChyeon committed Mar 10, 2024
1 parent e2deb84 commit aba0e0c
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ object MyPageDestinations {
const val MY_PAGE = "myPage"
const val BADGE = "badge"
const val ACCOUNT = "account"
const val MODIFY_NICKNAME = "modify_nickname"
const val WITHDRAWAL_REASON_SELECT = "withdrawal_reason_select"
const val WITHDRAWAL_CONFIRM = "withdrawal_confirm"
}
Expand Down
21 changes: 21 additions & 0 deletions core/design/src/main/res/drawable/ic_textfield_delete.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"
android:fillColor="#2C2F33"/>
<path
android:pathData="M8,16L16,8"
android:strokeWidth="2.3"
android:fillColor="#00000000"
android:strokeColor="#63666A"
android:strokeLineCap="round"/>
<path
android:pathData="M8,8L16,16"
android:strokeWidth="2.3"
android:fillColor="#00000000"
android:strokeColor="#63666A"
android:strokeLineCap="round"/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class MyPageContract {
val wineGradeStandard: List<WineGradeStandard> = emptyList(),
val isWineGradeStandardDialogOpen: Boolean = false,
val sommelierBadges: List<WineBadge> = emptyList(),
val newNickname: String = "",
val newNicknameErrorState: Boolean = false,
val activityBadges: List<WineBadge> = emptyList(),
val withdrawalReason: String = "이유를 선택해주세요.",
val isWithdrawalReasonDirectInput: Boolean = false,
Expand Down Expand Up @@ -51,4 +53,8 @@ class MyPageContract {

}

companion object {
const val NEW_NICKNAME_MAX_LENGTH = 9
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.teamwiney.core.common.WineyAppState
import com.teamwiney.core.common.WineyBottomSheetState
import com.teamwiney.core.common.navigation.MyPageDestinations
import com.teamwiney.mypage.account.MyPageAccountScreen
import com.teamwiney.mypage.account.MyPageModifyNicknameScreen
import com.teamwiney.mypage.account.MyPageWithdrawalConfirmScreen
import com.teamwiney.mypage.account.MyPageWithdrawalReasonSelectScreen
import com.teamwiney.mypage.badge.MyPageBadgeScreen
Expand Down Expand Up @@ -62,6 +63,18 @@ fun NavGraphBuilder.myPageGraph(
)
}

composable(route = MyPageDestinations.MODIFY_NICKNAME) {
val backStackEntry = rememberNavControllerBackStackEntry(
entry = it,
navController = appState.navController,
graph = MyPageDestinations.ROUTE
)
MyPageModifyNicknameScreen(
appState = appState,
viewModel = hiltViewModel(backStackEntry)
)
}

composable(route = MyPageDestinations.WITHDRAWAL_REASON_SELECT) {
val backStackEntry = rememberNavControllerBackStackEntry(
entry = it,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ fun MyProfileMenuItem(
) {
Text(
text = menu,
style = WineyTheme.typography.bodyB1.copy(
style = WineyTheme.typography.bodyM1.copy(
color = WineyTheme.colors.gray_400
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.navigation.navOptions
import com.teamwiney.core.common.base.BaseViewModel
import com.teamwiney.core.common.navigation.AuthDestinations
import com.teamwiney.core.common.navigation.HomeDestinations
import com.teamwiney.core.common.navigation.MyPageDestinations
import com.teamwiney.core.common.util.Constants.ACCESS_TOKEN
import com.teamwiney.core.common.util.Constants.DEVICE_ID
import com.teamwiney.core.common.util.Constants.REFRESH_TOKEN
Expand Down Expand Up @@ -71,7 +72,12 @@ class MyPageViewModel @Inject constructor(
is ApiResult.Success -> {
val result = it.data.result

updateState(currentState.copy(nickname = result.nickname))
updateState(
currentState.copy(
nickname = result.nickname,
newNickname = result.nickname
)
)
}

is ApiResult.ApiError -> {
Expand Down Expand Up @@ -237,6 +243,39 @@ class MyPageViewModel @Inject constructor(
}
}

fun modifyNickname() = viewModelScope.launch {
authRepository.modifyUserNickname(
currentState.newNickname
).onStart {
updateState(currentState.copy(isLoading = true))
}.collect {
updateState(currentState.copy(isLoading = false))

when (it) {
is ApiResult.Success -> {
postEffect(
MyPageContract.Effect.NavigateTo(
destination = MyPageDestinations.MY_PAGE,
navOptions = navOptions {
popUpTo(MyPageDestinations.MY_PAGE) {
inclusive = true
}
}
)
)
}

is ApiResult.ApiError -> {
postEffect(MyPageContract.Effect.ShowSnackBar(it.message))
}

else -> {
postEffect(MyPageContract.Effect.ShowSnackBar("네트워크 오류가 발생했습니다."))
}
}
}
}

fun logOut() = viewModelScope.launch {
val deviceId = runBlocking { dataStoreRepository.getStringValue(DEVICE_ID).first() }

Expand Down Expand Up @@ -284,4 +323,12 @@ class MyPageViewModel @Inject constructor(
)
)
}

fun updateNewNickname(nickname: String) = viewModelScope.launch {
updateState(
currentState.copy(
newNickname = nickname
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,33 @@ package com.teamwiney.mypage.account
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import com.teamwiney.core.common.WineyAppState
import com.teamwiney.core.common.WineyBottomSheetState
import com.teamwiney.core.common.navigation.MyPageDestinations
import com.teamwiney.core.design.R
import com.teamwiney.mypage.MyPageContract
import com.teamwiney.mypage.MyPageViewModel
import com.teamwiney.mypage.components.MyPageLogOutBottomSheet
import com.teamwiney.ui.components.HeightSpacer
import com.teamwiney.ui.components.HeightSpacerWithLine
import com.teamwiney.ui.components.TopBar
import com.teamwiney.ui.theme.WineyTheme
Expand Down Expand Up @@ -86,12 +93,37 @@ fun MyPageAccountScreen(
.background(WineyTheme.colors.background_1)
) {
TopBar(
content = "WINEY 계정"
content = "계정 설정"
) {
appState.navController.navigateUp()
}
HeightSpacer(height = 19.dp)
Box(
modifier = Modifier
.clickable { appState.navigate(MyPageDestinations.MODIFY_NICKNAME) }
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 20.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = "닉네임 수정",
style = WineyTheme.typography.bodyM1.copy(
color = WineyTheme.colors.gray_400
)
)

Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.ic_arrow_right),
contentDescription = "IC_ARROW_RIGHT",
tint = Color.Unspecified
)
}
}
HeightSpacerWithLine(color = WineyTheme.colors.gray_900)
Box(
modifier = Modifier
.clickable { viewModel.processEvent(MyPageContract.Event.LogOut) }
Expand All @@ -101,8 +133,8 @@ fun MyPageAccountScreen(
.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 19.dp),
text = "로그아웃",
style = WineyTheme.typography.bodyB1.copy(
color = WineyTheme.colors.gray_50
style = WineyTheme.typography.bodyM1.copy(
color = WineyTheme.colors.gray_400
)
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.teamwiney.mypage.account

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Text
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.teamwiney.core.common.WineyAppState
import com.teamwiney.core.design.R
import com.teamwiney.mypage.MyPageContract
import com.teamwiney.mypage.MyPageContract.Companion.NEW_NICKNAME_MAX_LENGTH
import com.teamwiney.mypage.MyPageViewModel
import com.teamwiney.ui.components.HeightSpacer
import com.teamwiney.ui.components.TopBar
import com.teamwiney.ui.components.WButton
import com.teamwiney.ui.components.WTextField
import com.teamwiney.ui.theme.WineyTheme
import kotlinx.coroutines.flow.collectLatest

@Composable
fun MyPageModifyNicknameScreen(
appState: WineyAppState,
viewModel: MyPageViewModel
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val effectFlow = viewModel.effect
val keyboardController = LocalSoftwareKeyboardController.current

LaunchedEffect(true) {
effectFlow.collectLatest { effect ->
when (effect) {
is MyPageContract.Effect.NavigateTo -> {
appState.navigate(effect.destination, effect.navOptions)
}

is MyPageContract.Effect.ShowSnackBar -> {
appState.showSnackbar(effect.message)
}

else -> { }
}
}
}

Column(
modifier = Modifier
.fillMaxSize()
.statusBarsPadding()
.background(WineyTheme.colors.background_1)
) {
TopBar {
appState.navController.navigateUp()
}
Column(
modifier = Modifier.padding(horizontal = 24.dp)
) {
Text(
text = "닉네임을 변경해주세요",
style = WineyTheme.typography.title1.copy(
color = WineyTheme.colors.gray_50
)
)
HeightSpacer(height = 14.dp)
Text(
text = "언제든지 다시 바꿀 수 있어요!",
style = WineyTheme.typography.bodyM2.copy(
color = WineyTheme.colors.gray_700
)
)
HeightSpacer(height = 30.dp)
Text(
text = if (uiState.newNicknameErrorState) "최대 9자로 입력해주세요." else "닉네임",
color = if (uiState.newNicknameErrorState) WineyTheme.colors.error else WineyTheme.colors.gray_600,
style = if (uiState.newNicknameErrorState) WineyTheme.typography.bodyM2 else WineyTheme.typography.bodyB2
)
HeightSpacer(10.dp)
WTextField(
value = uiState.newNickname,
onValueChanged = {
viewModel.updateNewNickname(it)
},
trailingIcon = {
Icon(
modifier = Modifier.size(24.dp).clickable {
viewModel.updateNewNickname("")
},
painter = painterResource(id = R.drawable.ic_textfield_delete),
contentDescription = "IC_TEXT_DELETE",
tint = Color.Unspecified
)
},
placeholderText = "${NEW_NICKNAME_MAX_LENGTH}자리 입력",
maxLength = NEW_NICKNAME_MAX_LENGTH,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
keyboardActions = KeyboardActions(
onDone = {
keyboardController?.hide()
viewModel.modifyNickname()
}
),
onErrorState = uiState.newNicknameErrorState
)
Spacer(modifier = Modifier.weight(1f))
WButton(
text = "변경",
onClick = {
keyboardController?.hide()
viewModel.modifyNickname()
},
enabled = uiState.newNickname.isNotEmpty(),
modifier = Modifier.padding(bottom = 30.dp)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ fun MyPageWithdrawalReasonSelectScreen(
val effectFlow = viewModel.effect

LaunchedEffect(true) {

effectFlow.collectLatest { effect ->
when (effect) {
is MyPageContract.Effect.NavigateTo -> {
Expand Down

0 comments on commit aba0e0c

Please sign in to comment.