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

Feature/#94 my account #97

Merged
merged 17 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b432605
feat/#94 : ๊ณ„์ • ๊ด€๋ฆฌ ๊ธฐ๋Šฅ
BEEEAM-J Jan 14, 2024
04f41cb
Merge branch 'develop' into feature/#94-my-account
BEEEAM-J Jan 14, 2024
5033ea2
rename/#94 : Change Password, Withdrawal -> Reset Password, Quit
BEEEAM-J Jan 14, 2024
6695a5f
feat/#94 : ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ
BEEEAM-J Jan 15, 2024
b5943f4
Merge branch 'develop' into feature/#94-my-account
BEEEAM-J Jan 15, 2024
5a3d98b
move/#94 : ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ Login -> MyInfo ๋ชจ๋“ˆ๋กœ ์ด๋™
BEEEAM-J Jan 15, 2024
4e1d5f0
remove/#94 : Custom NavType
BEEEAM-J Jan 15, 2024
4de229d
feat/#94 : ํšŒ์› ํƒˆํ‡ด ๊ธฐ๋Šฅ
BEEEAM-J Jan 15, 2024
d19a75f
chore/#94 : ktlint
BEEEAM-J Jan 15, 2024
e005e1e
refactor/#94 : TextField update ํ•จ์ˆ˜ intent -> blockingIntent ๋ณ€๊ฒฝ
BEEEAM-J Jan 16, 2024
5dc30d8
refactor/#94 : ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” ๋กœ์ง ์ˆ˜์ •
BEEEAM-J Jan 16, 2024
324b731
refactor/#94 : MyAccountViewModel ViewModel getUserInfoUseCase() ์˜ˆ์™ธ ์ฒ˜โ€ฆ
BEEEAM-J Jan 16, 2024
4b402ad
chore/#94 : ktlint
BEEEAM-J Jan 16, 2024
644c36b
feat/#94 : MyAccountScreen HorizontalDivider ์ˆ˜์ •
BEEEAM-J Jan 16, 2024
8ce2fc0
feat/#94: ํšŒ์›ํƒˆํ‡ด, ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ๋™์ž‘ ์ˆ˜์ •
jinukeu Jan 17, 2024
f552de9
refactor/#94: Quit, MyInfoScreen ๋ฆฌํŒฉํ† ๋ง
jinukeu Jan 17, 2024
4e27cf1
chore/#94: ktlint format
jinukeu Jan 17, 2024
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
1 change: 1 addition & 0 deletions feature/login/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ android {

dependencies {
implementation(projects.domain.login)
implementation(projects.domain.user)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ data class MyInfoState(
sealed interface MyInfoSideEffect {
data object NavigateNotice : MyInfoSideEffect
data object NavigateMyEvaluation : MyInfoSideEffect
data object NavigateMyAccount : MyInfoSideEffect
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ fun MyInfoRoute(
viewModel: MyInfoViewModel = hiltViewModel(),
navigateNotice: () -> Unit,
navigateMyEvaluation: () -> Unit,
navigateMyAccount: () -> Unit,
) {
val scrollState = rememberScrollState()
val uiState = viewModel.collectAsState().value
viewModel.collectSideEffect { sideEffect ->
when (sideEffect) {
MyInfoSideEffect.NavigateNotice -> navigateNotice()
is MyInfoSideEffect.NavigateNotice -> navigateNotice()
is MyInfoSideEffect.NavigateMyEvaluation -> navigateMyEvaluation()
is MyInfoSideEffect.NavigateMyAccount -> navigateMyAccount()
}
}

Expand All @@ -68,6 +70,7 @@ fun MyInfoRoute(
scrollState = scrollState,
onClickNoticeButton = viewModel::navigateNotice,
onClickMyEvaluationButton = viewModel::navigateMyEvaluation,
onClickMyAccountButton = viewModel::navigateMyAccount,
)
}

Expand All @@ -78,6 +81,7 @@ fun MyInfoScreen(
scrollState: ScrollState,
onClickNoticeButton: () -> Unit,
onClickMyEvaluationButton: () -> Unit,
onClickMyAccountButton: () -> Unit,
) {
val myList = immutableListOf(
R.string.my_info_point,
Expand Down Expand Up @@ -142,6 +146,7 @@ fun MyInfoScreen(
MyInfoMenuItem(
title = stringResource(R.string.my_info_account_manage),
iconId = R.drawable.ic_my_info_setting,
onClickItem = onClickMyAccountButton,
)
}
}
Expand Down Expand Up @@ -327,6 +332,7 @@ fun MyInfoScreenScreenPreview() {
scrollState = scrollState,
onClickNoticeButton = {},
onClickMyEvaluationButton = {},
onClickMyAccountButton = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ class MyInfoViewModel @Inject constructor(

fun navigateNotice() = intent { postSideEffect(MyInfoSideEffect.NavigateNotice) }
fun navigateMyEvaluation() = intent { postSideEffect(MyInfoSideEffect.NavigateMyEvaluation) }
fun navigateMyAccount() = intent { postSideEffect(MyInfoSideEffect.NavigateMyAccount) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.suwiki.feature.myinfo.myaccount

data class MyAccountState(
val isLoading: Boolean = false,
val userId: String = "",
val userEmail: String = "",
)

sealed interface MyAccountSideEffect {
data object PopBackStack : MyAccountSideEffect
data object NavigateResetPassword : MyAccountSideEffect
data object NavigateQuit : MyAccountSideEffect
data class HandleException(val throwable: Throwable) : MyAccountSideEffect
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package com.suwiki.feature.myinfo.myaccount

import androidx.compose.foundation.background
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.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
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 com.suwiki.core.designsystem.component.appbar.SuwikiAppBarWithTitle
import com.suwiki.core.designsystem.theme.Gray95
import com.suwiki.core.designsystem.theme.GrayF6
import com.suwiki.core.designsystem.theme.SuwikiTheme
import com.suwiki.core.designsystem.theme.White
import com.suwiki.core.ui.extension.suwikiClickable
import com.suwiki.feature.myinfo.R
import org.orbitmvi.orbit.compose.collectAsState
import org.orbitmvi.orbit.compose.collectSideEffect

@Composable
fun MyAccountRoute(
viewModel: MyAccountViewModel = hiltViewModel(),
popBackStack: () -> Unit,
navigateResetPassword: () -> Unit = {},
navigateQuit: () -> Unit = {},
handleException: (Throwable) -> Unit,
) {
val uiState = viewModel.collectAsState().value
viewModel.collectSideEffect { sideEffect ->
when (sideEffect) {
MyAccountSideEffect.PopBackStack -> popBackStack()
is MyAccountSideEffect.NavigateResetPassword -> navigateResetPassword()
is MyAccountSideEffect.NavigateQuit -> navigateQuit()
is MyAccountSideEffect.HandleException -> handleException(sideEffect.throwable)
}
}

LaunchedEffect(key1 = Unit) {
viewModel.initData()
}

MyAccountScreen(
uiState = uiState,
popBackStack = viewModel::popBackStack,
onClickResetPassword = viewModel::navigateResetPassword,
onClickLogout = { /*TODO(LOGOUT)*/ },
onClickQuit = viewModel::navigateQuit,
)
}

@Composable
fun MyAccountScreen(
uiState: MyAccountState = MyAccountState(),
popBackStack: () -> Unit = {},
onClickResetPassword: () -> Unit = {},
onClickLogout: () -> Unit = {},
onClickQuit: () -> Unit = {},
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(White),
) {
SuwikiAppBarWithTitle(
showBackIcon = true,
showCloseIcon = false,
onClickBack = popBackStack,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 14.dp),
text = stringResource(R.string.word_my_account),
style = SuwikiTheme.typography.body2,
)
UserInfoRowContainer(
userInfo = stringResource(R.string.word_login_id),
userInfoValue = uiState.userId,
)
UserInfoRowContainer(
userInfo = stringResource(R.string.word__authentication_email),
userInfoValue = uiState.userEmail,
)
Spacer(modifier = Modifier.height(24.dp))
AlignContainer(
title = stringResource(R.string.word_reset_password),
onClick = onClickResetPassword,
)
AlignContainer(
title = stringResource(R.string.word_logout),
onClick = onClickLogout,
)
AlignContainer(
title = stringResource(R.string.word_quit),
onClick = onClickQuit,
)
}
}

@Composable
fun AlignContainer(
modifier: Modifier = Modifier,
title: String,
onClick: () -> Unit = {},
) {
Box(
modifier = modifier
.fillMaxWidth()
.suwikiClickable(onClick = onClick)
.padding(horizontal = 24.dp, vertical = 14.dp),
) {
Text(
text = title,
style = SuwikiTheme.typography.body2,
)
}
}

@Composable
fun UserInfoRowContainer(
modifier: Modifier = Modifier,
userInfo: String,
userInfoValue: String,
) {
Column {
Row(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 14.dp),
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = userInfo,
style = SuwikiTheme.typography.caption2,
color = Gray95,
)
Text(
text = userInfoValue,
style = SuwikiTheme.typography.body5,
)
}
HorizontalDivider(
modifier = Modifier
.background(GrayF6),
)
}
}

@Preview
@Composable
fun MyAccountScreenPreview() {
SuwikiTheme {
MyAccountScreen()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.suwiki.feature.myinfo.myaccount

import androidx.lifecycle.ViewModel
import com.suwiki.core.model.user.User
import com.suwiki.domain.user.usecase.GetUserInfoUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import org.orbitmvi.orbit.Container
import org.orbitmvi.orbit.ContainerHost
import org.orbitmvi.orbit.syntax.simple.intent
import org.orbitmvi.orbit.syntax.simple.postSideEffect
import org.orbitmvi.orbit.syntax.simple.reduce
import org.orbitmvi.orbit.viewmodel.container
import javax.inject.Inject

@HiltViewModel
class MyAccountViewModel @Inject constructor(
val getUserInfoUseCase: GetUserInfoUseCase,
) : ContainerHost<MyAccountState, MyAccountSideEffect>, ViewModel() {
override val container: Container<MyAccountState, MyAccountSideEffect> = container(MyAccountState())

fun initData() = intent {
getUserInfoUseCase().collect(::updateUserIdAndEmail).runCatching {}
BEEEAM-J marked this conversation as resolved.
Show resolved Hide resolved
.onFailure {
postSideEffect(MyAccountSideEffect.HandleException(it))
}
}

private fun updateUserIdAndEmail(user: User) = intent {
reduce {
state.copy(
userId = user.userId,
userEmail = user.email,
)
}
}

fun popBackStack() = intent { postSideEffect(MyAccountSideEffect.PopBackStack) }
fun navigateResetPassword() = intent { postSideEffect(MyAccountSideEffect.NavigateResetPassword) }
fun navigateQuit() = intent { postSideEffect(MyAccountSideEffect.NavigateQuit) }
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,73 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.suwiki.feature.myinfo.MyInfoRoute
import com.suwiki.feature.myinfo.myaccount.MyAccountRoute
import com.suwiki.feature.myinfo.quit.QuitRoute
import com.suwiki.feature.myinfo.resetpassword.ResetPasswordRoute

fun NavController.navigateMyInfo(navOptions: NavOptions) {
navigate(MyInfoRoute.route, navOptions)
}

fun NavController.navigateMyAccount() {
navigate(MyInfoRoute.myAccountRoute)
}

fun NavController.navigateResetPassword() {
navigate(MyInfoRoute.resetPasswordRoute)
}

fun NavController.navigateQuit() {
navigate(MyInfoRoute.quitRoute)
}

fun NavGraphBuilder.myInfoNavGraph(
padding: PaddingValues,
popBackStack: () -> Unit = {},
navigateNotice: () -> Unit = {},
navigateMyEvaluation: () -> Unit = {},
navigateMyAccount: () -> Unit = {},
navigateResetPassword: () -> Unit = {},
navigateQuit: () -> Unit = {},
navigateFindPassword: () -> Unit = {},
navigateLogin: () -> Unit = {},
handleException: (Throwable) -> Unit = {},
) {
composable(route = MyInfoRoute.route) {
MyInfoRoute(
padding = padding,
navigateNotice = navigateNotice,
navigateMyEvaluation = navigateMyEvaluation,
navigateMyAccount = navigateMyAccount,
)
}
composable(route = MyInfoRoute.myAccountRoute) {
MyAccountRoute(
popBackStack = popBackStack,
navigateResetPassword = navigateResetPassword,
navigateQuit = navigateQuit,
handleException = handleException,
)
}
composable(route = MyInfoRoute.resetPasswordRoute) {
ResetPasswordRoute(
popBackStack = popBackStack,
navigateFindPassword = navigateFindPassword,
navigateLogin = navigateLogin,
handleException = handleException,
)
}
composable(route = MyInfoRoute.quitRoute) {
QuitRoute(
popBackStack = popBackStack,
handleException = handleException,
)
}
}

object MyInfoRoute {
const val route = "my-info"
const val myAccountRoute = "my-account"
const val resetPasswordRoute = "reset-password"
const val quitRoute = "quit"
}
Loading