diff --git a/feature/mypage/src/main/java/org/sopt/mypage/MypageScreen.kt b/feature/mypage/src/main/java/org/sopt/mypage/MypageScreen.kt new file mode 100644 index 0000000..15f6578 --- /dev/null +++ b/feature/mypage/src/main/java/org/sopt/mypage/MypageScreen.kt @@ -0,0 +1,128 @@ +package org.sopt.mypage + +import android.annotation.SuppressLint +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect +import org.sopt.designsystem.component.button.RegularButton +import org.sopt.designsystem.ui.theme.NOWSOPTAndroidTheme + +@Composable +fun MypageRoute( + viewModel: MypageViewModel = hiltViewModel(), + navigateToLoginScreen: () -> Unit, +) { + val state = viewModel.collectAsState().value + val snackBarHostState = remember { SnackbarHostState() } + + viewModel.collectSideEffect { sideEffect -> + when (sideEffect) { + MypageSideEffect.LogoutSuccess -> { + navigateToLoginScreen() + } + MypageSideEffect.WithdrawSuccess -> { + navigateToLoginScreen() + } + } + } + + MypageScreen( + snackBarHostState = snackBarHostState, + onClickLogoutButton = viewModel::logout, + onClickWithDrawButton = viewModel::signout, + state = state + ) +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun MypageScreen( + snackBarHostState: SnackbarHostState, + onClickLogoutButton: () -> Unit = {}, + onClickWithDrawButton: () -> Unit = {}, + state: MypageState, +) { + Scaffold( + snackbarHost = { SnackbarHost(hostState = snackBarHostState) } + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(top = 20.dp, bottom = 20.dp, start = 20.dp, end = 20.dp) + ) { + Column { + MypageText( + title = "이름 : ", + text = state.name + ) + Spacer(modifier = Modifier.height(30.dp)) + MypageText( + title = "취미 : ", + text = state.hobby + ) + Spacer(modifier = Modifier.weight(1f)) + RegularButton( + text = "로그아웃", + onClick = onClickLogoutButton + ) + Spacer(modifier = Modifier.height(20.dp)) + RegularButton( + text = "회원탈퇴", + onClick = onClickWithDrawButton + ) + Spacer(modifier = Modifier.height(30.dp)) + Spacer(modifier = Modifier.height(56.dp)) + } + } + } +} + +@Composable +fun MypageText( + title: String = "", + text: String = "", + style: TextStyle = MaterialTheme.typography.titleLarge, +) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = title, + style = style, + textAlign = TextAlign.Center + ) + Text( + text = text, + style = style, + textAlign = TextAlign.Center + ) + } +} + +@Preview(showBackground = true) +@Composable +fun MypageScreenPreview() { + NOWSOPTAndroidTheme { + //MypageRoute() + } +} \ No newline at end of file diff --git a/feature/mypage/src/main/java/org/sopt/mypage/MypageViewModel.kt b/feature/mypage/src/main/java/org/sopt/mypage/MypageViewModel.kt new file mode 100644 index 0000000..c69ede5 --- /dev/null +++ b/feature/mypage/src/main/java/org/sopt/mypage/MypageViewModel.kt @@ -0,0 +1,47 @@ +package org.sopt.mypage + +import androidx.lifecycle.ViewModel +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 org.sopt.domain.repo.UserDataRepository +import org.sopt.model.User +import javax.inject.Inject + +@HiltViewModel +class MypageViewModel @Inject constructor( + private val userDataRepository: UserDataRepository, +) : ContainerHost, ViewModel() { + override val container: Container = container(MypageState()) + + init { + getUserData() + } + + private fun getUserData() = intent { + userDataRepository.getUserData().collect { + reduce { state.copy(name = it.name, hobby = it.hobby) } + } + } + + fun logout() = intent { + setAutoLoginFalse() + .onSuccess { postSideEffect(MypageSideEffect.LogoutSuccess) } + } + + fun signout() = intent { + deleteUserData() + .onSuccess { postSideEffect(MypageSideEffect.WithdrawSuccess) } + } + + private suspend fun setAutoLoginFalse() = + runCatching { userDataRepository.setAutoLogin(false) } + + private suspend fun deleteUserData() = + runCatching { userDataRepository.deleteUserData() } + +} \ No newline at end of file diff --git a/feature/mypage/src/main/java/org/sopt/mypage/navigation/MypageNavigation.kt b/feature/mypage/src/main/java/org/sopt/mypage/navigation/MypageNavigation.kt new file mode 100644 index 0000000..043eb13 --- /dev/null +++ b/feature/mypage/src/main/java/org/sopt/mypage/navigation/MypageNavigation.kt @@ -0,0 +1,25 @@ +package org.sopt.mypage.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import org.sopt.mypage.MypageRoute + +fun NavController.navigateMypage(navOptions: NavOptions) { + navigate(MypageRoute.route, navOptions) +} + +fun NavGraphBuilder.MypageNavGraph( + navigateToLoginScreen: () -> Unit, +){ + composable(route = MypageRoute.route) { navBackStackEntry -> + MypageRoute( + navigateToLoginScreen = navigateToLoginScreen + ) + } +} + +object MypageRoute { + const val route = "mypage" +} \ No newline at end of file diff --git a/feature/mypage/src/test/java/org/sopt/mypage/ExampleUnitTest.kt b/feature/mypage/src/test/java/org/sopt/mypage/ExampleUnitTest.kt new file mode 100644 index 0000000..5972ca2 --- /dev/null +++ b/feature/mypage/src/test/java/org/sopt/mypage/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package org.sopt.mypage + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file