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

[TNT-114] 회원가입 화면 플로우 연결 #37

Merged
merged 16 commits into from
Jan 26, 2025
Merged
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
[TNT-114] chore: TNT-115 branch rebase
- develop과 머지 된 TNT-115 branch
SeonJeongk committed Jan 26, 2025
commit 37afaee445e483ae05292dba9e275831dab39ce7
1 change: 1 addition & 0 deletions feature/main/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ dependencies {
implementation(projects.feature.trainer.connect)
implementation(projects.feature.trainee.connect)
implementation(projects.feature.trainee.signup)
implementation(projects.feature.trainer.signup)

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
6 changes: 6 additions & 0 deletions feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import co.kr.tnt.login.navigation.loginScreen
import co.kr.tnt.trainee.signup.navigation.traineeSignUpScreen
import co.kr.tnt.trainee.connect.navigation.traineeConnectScreen
import co.kr.tnt.trainer.connect.navigation.trainerConnectScreen
import co.kr.tnt.trainer.signup.navigation.trainerSignUpScreen

@Composable
fun TnTNavHost(
@@ -30,10 +31,15 @@ fun TnTNavHost(
navigateToHome = { },
navigateToSignup = { },
)
// TODO connect로 이동하게 수정
traineeSignUpScreen(
navigateToPrevious = { navController.popBackStack() },
navigateToHome = { navController.navigateToHome(false, clearBackStack = true) },
)
trainerSignUpScreen(
navigateToPrevious = { navController.popBackStack() },
navigateToHome = { navController.navigateToHome(false, clearBackStack = true) },
)
trainerConnectScreen(
navigateToPrevious = { navController.popBackStack() },
navigateToHome = {
Original file line number Diff line number Diff line change
@@ -41,7 +41,10 @@ import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest

@Composable
fun TrainerProfileSetupScreen() {
fun TrainerProfileSetupScreen(
onBackClick: () -> Unit,
onNextClick: () -> Unit,
) {
val context = LocalContext.current

// TODO 상태 관리 따로 빼기
@@ -63,7 +66,7 @@ fun TrainerProfileSetupScreen() {
)

Scaffold(
topBar = { TnTTopBarWithBackButton(onBackClick = {}) },
topBar = { TnTTopBarWithBackButton(onBackClick = {onBackClick()}) },
containerColor = TnTTheme.colors.commonColors.Common0,
) { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
@@ -112,12 +115,11 @@ fun TrainerProfileSetupScreen() {
warningMessage = stringResource(R.string.text_length_warning, maxLength),
)
}
// TODO 트레이너 프로필 생성 완료 화면으로 이동
TnTBottomButton(
text = stringResource(R.string.next),
modifier = Modifier.align(Alignment.BottomCenter),
enabled = text.isNotBlank() && !isWarning,
onClick = { },
onClick = { onNextClick() },
)
}
}
@@ -134,6 +136,9 @@ private fun validateInput(input: String): String {
@Composable
private fun TrainerProfileSetupScreenPreview() {
TnTTheme {
TrainerProfileSetupScreen()
TrainerProfileSetupScreen(
onBackClick = {},
onNextClick = {},
)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package co.kr.tnt.trainer.signup

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -25,59 +27,69 @@ import coil.compose.rememberAsyncImagePainter

@Composable
fun TrainerSignUpCompleteScreen(
modifier: Modifier = Modifier,
onBackClick: () -> Unit,
onNextClick: () -> Unit,
) {
BackHandler { onBackClick() }

// TODO 이름, 프로필 이미지 불러오기
val name = "김헬짱"
val profileImage = "https://buly.kr/7FQeS5M"

Box(
modifier = modifier
.fillMaxSize()
.background(TnTTheme.colors.commonColors.Common0),
contentAlignment = Alignment.Center,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
Scaffold(
containerColor = TnTTheme.colors.commonColors.Common0,
) { innerPadding ->
Box(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 66.dp),
.padding(innerPadding)
.fillMaxSize()
.background(TnTTheme.colors.commonColors.Common0),
contentAlignment = Alignment.Center,
) {
Text(
text = stringResource(R.string.nice_to_meet_you_trainer, name),
color = TnTTheme.colors.neutralColors.Neutral950,
style = TnTTheme.typography.h1,
textAlign = Center,
modifier = Modifier.padding(horizontal = 24.dp),
)
Spacer(Modifier.padding(top = 10.dp))
Text(
text = stringResource(R.string.chemistry_boom_with_trainee),
color = TnTTheme.colors.neutralColors.Neutral500,
style = TnTTheme.typography.body1Medium,
textAlign = Center,
)
Spacer(Modifier.padding(top = 28.dp))
TnTProfileImage(
defaultImage = painterResource(DefaultUserProfile.Trainer.image),
image = rememberAsyncImagePainter(profileImage),
imageSize = 200.dp,
showEditButton = false,
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 66.dp),
) {
Text(
text = stringResource(R.string.nice_to_meet_you_trainer, name),
color = TnTTheme.colors.neutralColors.Neutral950,
style = TnTTheme.typography.h1,
textAlign = Center,
modifier = Modifier.padding(horizontal = 24.dp),
)
Spacer(Modifier.padding(top = 10.dp))
Text(
text = stringResource(R.string.chemistry_boom_with_trainee),
color = TnTTheme.colors.neutralColors.Neutral500,
style = TnTTheme.typography.body1Medium,
textAlign = Center,
)
Spacer(Modifier.padding(top = 28.dp))
TnTProfileImage(
defaultImage = painterResource(DefaultUserProfile.Trainer.image),
image = rememberAsyncImagePainter(profileImage),
imageSize = 200.dp,
showEditButton = false,
)
}
TnTBottomButton(
text = stringResource(R.string.start),
onClick = { onNextClick() },
modifier = Modifier.align(Alignment.BottomCenter),
)
}
// TODO 연결코드 생성 화면으로 이동
TnTBottomButton(
text = stringResource(R.string.start),
onClick = { },
modifier = Modifier.align(Alignment.BottomCenter),
)
}
}

@Preview(showBackground = true)
@Composable
private fun TrainerSignUpCompleteScreenPreview() {
TnTTheme {
TrainerSignUpCompleteScreen()
TrainerSignUpCompleteScreen(
onBackClick = {},
onNextClick = {},
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package co.kr.tnt.trainer.signup

import co.kr.tnt.ui.base.UiEvent
import co.kr.tnt.ui.base.UiSideEffect
import co.kr.tnt.ui.base.UiState

internal class TrainerSignUpContract {
data class TrainerSignUpUiState(
val page: TrainerSignUpPage = TrainerSignUpPage.ProfileSetUp,
val name: String = "",
) : UiState

sealed interface TrainerSignUpUiEvent : UiEvent {
data object OnNextClick : TrainerSignUpUiEvent
data object OnBackClick : TrainerSignUpUiEvent
}

sealed interface TrainerSignUpEffect : UiSideEffect {
data object NavigateToBack : TrainerSignUpEffect
data object NavigateToConnect : TrainerSignUpEffect
}

enum class TrainerSignUpPage {
ProfileSetUp,
SignUpComplete,
;

companion object {
fun getPreviousPage(currentPage: TrainerSignUpPage): TrainerSignUpPage {
return when (currentPage) {
SignUpComplete -> ProfileSetUp
else -> error("No previous page defined for $currentPage")
}
}

fun getNextPage(currentPage: TrainerSignUpPage): TrainerSignUpPage {
return when (currentPage) {
ProfileSetUp -> SignUpComplete
else -> error("No next page defined for $currentPage")
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package co.kr.tnt.trainer.signup

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.kr.tnt.trainer.signup.TrainerSignUpContract.TrainerSignUpUiEvent
import co.kr.tnt.trainer.signup.TrainerSignUpContract.TrainerSignUpUiState

@Composable
internal fun TrainerSignUpRoute(
navigateToPrevious: () -> Unit,
navigateToConnect: () -> Unit,
viewModel: TrainerSignUpViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

TrainerSignUpScreen(
state = uiState,
onNextClick = { viewModel.setEvent(TrainerSignUpUiEvent.OnNextClick) },
onBackClick = { viewModel.setEvent(TrainerSignUpUiEvent.OnBackClick) },
)

LaunchedEffect(viewModel.effect) {
viewModel.effect.collect { effect ->
when (effect) {
TrainerSignUpContract.TrainerSignUpEffect.NavigateToBack -> navigateToPrevious()
TrainerSignUpContract.TrainerSignUpEffect.NavigateToConnect -> navigateToConnect()
}
}
}
}

@Composable
private fun TrainerSignUpScreen(
state: TrainerSignUpUiState,
onNextClick: () -> Unit,
onBackClick: () -> Unit,
) {
when (state.page) {
TrainerSignUpContract.TrainerSignUpPage.ProfileSetUp -> TrainerProfileSetupScreen(
onNextClick = onNextClick,
onBackClick = onBackClick,
)
TrainerSignUpContract.TrainerSignUpPage.SignUpComplete -> TrainerSignUpCompleteScreen(
onNextClick = onNextClick,
onBackClick = onBackClick,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package co.kr.tnt.trainer.signup

import co.kr.tnt.trainer.signup.TrainerSignUpContract.TrainerSignUpEffect
import co.kr.tnt.trainer.signup.TrainerSignUpContract.TrainerSignUpPage
import co.kr.tnt.trainer.signup.TrainerSignUpContract.TrainerSignUpUiEvent
import co.kr.tnt.trainer.signup.TrainerSignUpContract.TrainerSignUpUiState
import co.kr.tnt.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
internal class TrainerSignUpViewModel @Inject constructor() :
BaseViewModel<TrainerSignUpUiState, TrainerSignUpUiEvent, TrainerSignUpEffect>(
TrainerSignUpUiState(),
) {
override suspend fun handleEvent(event: TrainerSignUpUiEvent) {
when (event) {
TrainerSignUpUiEvent.OnNextClick -> navigateToNext()
TrainerSignUpUiEvent.OnBackClick -> navigateToBack()
}
}

private fun navigateToNext() {
val nextPage = when (currentState.page) {
TrainerSignUpPage.SignUpComplete -> {
sendEffect(TrainerSignUpEffect.NavigateToConnect)
return
}

else -> TrainerSignUpPage.getNextPage(currentState.page)
}
updateState { copy(page = nextPage) }
}

private fun navigateToBack() {
val previousPage = when (currentState.page) {
TrainerSignUpPage.ProfileSetUp -> {
sendEffect(TrainerSignUpEffect.NavigateToBack)
return
}

else -> TrainerSignUpPage.getPreviousPage(currentState.page)
}
updateState { copy(page = previousPage) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package co.kr.tnt.trainer.signup.navigation

import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptionsBuilder
import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import co.kr.tnt.navigation.Route
import co.kr.tnt.trainer.signup.TrainerSignUpRoute

fun NavController.navigateToTrainerSignUp(
navOptions: NavOptionsBuilder.() -> Unit = {},
) = navigate(
route = Route.TrainerSignUp,
builder = navOptions,
)

fun NavGraphBuilder.trainerSignUpScreen(
navigateToPrevious: () -> Unit,
navigateToHome: (Boolean) -> Unit,
) {
composable<Route.TrainerSignUp> { backstackEntry ->
backstackEntry.toRoute<Route.TrainerSignUp>().apply {
// TODO 115 머지되면 connect로 이동
TrainerSignUpRoute(
navigateToPrevious = navigateToPrevious,
navigateToConnect = { navigateToHome(true) },
)
}
}
}