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 all 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
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import kotlinx.coroutines.CoroutineScope
@Composable
fun LaunchedEffectWithLifecycle(
key1: Any? = Unit,
key2: Any? = Unit,
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
action: suspend CoroutineScope.() -> Unit = {},
) {
LaunchedEffect(key1 = key1) {
LaunchedEffect(key1 = key1, key2 = key2) {
lifecycleOwner.lifecycle.repeatOnLifecycle(minActiveState) {
action()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class UserRepositoryImpl @Inject constructor(
id = id,
password = password,
)
logout()
}

override suspend fun getUserInfo(): Flow<User> = flow {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import kotlinx.collections.immutable.toPersistentList
import kotlinx.serialization.json.Json
import org.orbitmvi.orbit.Container
import org.orbitmvi.orbit.ContainerHost
import org.orbitmvi.orbit.annotation.OrbitExperimental
import org.orbitmvi.orbit.syntax.simple.blockingIntent
import org.orbitmvi.orbit.syntax.simple.intent
import org.orbitmvi.orbit.syntax.simple.postSideEffect
import org.orbitmvi.orbit.syntax.simple.reduce
Expand Down Expand Up @@ -128,7 +130,8 @@ class MyExamEvaluationEditViewModel @Inject constructor(
reduce { state.copy(examInfo = examInfoList.toPersistentList()) }
}

fun updateMyExamEvaluationValue(examEvaluationValue: String) = intent {
@OptIn(OrbitExperimental::class)
fun updateMyExamEvaluationValue(examEvaluationValue: String) = blockingIntent {
reduce { state.copy(examEvaluation = examEvaluationValue) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import kotlinx.collections.immutable.toPersistentList
import kotlinx.serialization.json.Json
import org.orbitmvi.orbit.Container
import org.orbitmvi.orbit.ContainerHost
import org.orbitmvi.orbit.annotation.OrbitExperimental
import org.orbitmvi.orbit.syntax.simple.blockingIntent
import org.orbitmvi.orbit.syntax.simple.intent
import org.orbitmvi.orbit.syntax.simple.postSideEffect
import org.orbitmvi.orbit.syntax.simple.reduce
Expand Down Expand Up @@ -129,7 +131,8 @@ class MyLectureEvaluationEditViewModel @Inject constructor(
reduce { state.copy(satisfactionRating = if (satisfactionRating < 0.5) 0.5F else satisfactionRating) }
}

fun updateMyLectureEvaluationValue(lectureEvaluationValue: String) = intent {
@OptIn(OrbitExperimental::class)
fun updateMyLectureEvaluationValue(lectureEvaluationValue: String) = blockingIntent {
reduce { state.copy(lectureEvaluation = lectureEvaluationValue) }
}

Expand Down
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 @@ -2,13 +2,17 @@ package com.suwiki.feature.login.navigation

import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.suwiki.feature.login.findid.FindIdRoute
import com.suwiki.feature.login.findpassword.FindPasswordRoute
import com.suwiki.feature.login.login.LoginRoute

fun NavController.navigateLogin() {
navigate(LoginRoute.route)
fun NavController.navigateLogin(navOptions: NavOptions? = null) {
navigate(
route = LoginRoute.route,
navOptions = navOptions,
)
}

fun NavController.navigateFindId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ data class MyInfoState(
sealed interface MyInfoSideEffect {
data object NavigateNotice : MyInfoSideEffect
data object NavigateMyEvaluation : MyInfoSideEffect
data object NavigateMyAccount : MyInfoSideEffect
data object ShowNeedLoginToast : MyInfoSideEffect
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -48,13 +49,18 @@ fun MyInfoRoute(
viewModel: MyInfoViewModel = hiltViewModel(),
navigateNotice: () -> Unit,
navigateMyEvaluation: () -> Unit,
navigateMyAccount: () -> Unit,
onShowToast: (String) -> Unit = {},
) {
val scrollState = rememberScrollState()
val uiState = viewModel.collectAsState().value
val context = LocalContext.current
viewModel.collectSideEffect { sideEffect ->
when (sideEffect) {
MyInfoSideEffect.NavigateNotice -> navigateNotice()
is MyInfoSideEffect.NavigateNotice -> navigateNotice()
is MyInfoSideEffect.NavigateMyEvaluation -> navigateMyEvaluation()
is MyInfoSideEffect.NavigateMyAccount -> navigateMyAccount()
MyInfoSideEffect.ShowNeedLoginToast -> onShowToast(context.getString(R.string.my_info_screen_need_login_toast))
}
}

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

Expand All @@ -78,6 +85,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 +150,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 +336,7 @@ fun MyInfoScreenScreenPreview() {
scrollState = scrollState,
onClickNoticeButton = {},
onClickMyEvaluationButton = {},
onClickMyAccountButton = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class MyInfoViewModel @Inject constructor(
) : ContainerHost<MyInfoState, MyInfoSideEffect>, ViewModel() {
override val container: Container<MyInfoState, MyInfoSideEffect> = container(MyInfoState())

private var isLoggedIn: Boolean = false

suspend fun checkLoggedIn() {
showLoadingScreen()
/* TODO ์—๋Ÿฌ ์ฒ˜๋ฆฌ */
Expand All @@ -27,6 +29,7 @@ class MyInfoViewModel @Inject constructor(

private fun reduceUser(user: User) = intent {
reduce {
isLoggedIn = user.isLoggedIn
state.copy(
showMyInfoCard = user.isLoggedIn,
loginId = user.userId,
Expand All @@ -40,4 +43,13 @@ class MyInfoViewModel @Inject constructor(

fun navigateNotice() = intent { postSideEffect(MyInfoSideEffect.NavigateNotice) }
fun navigateMyEvaluation() = intent { postSideEffect(MyInfoSideEffect.NavigateMyEvaluation) }
fun navigateMyAccount() = intent {
postSideEffect(
if (isLoggedIn) {
MyInfoSideEffect.NavigateMyAccount
} else {
MyInfoSideEffect.ShowNeedLoginToast
},
)
}
}
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,164 @@
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(color = GrayF6)
}
}

@Preview
@Composable
fun MyAccountScreenPreview() {
SuwikiTheme {
MyAccountScreen()
}
}
Loading