Skip to content

Commit

Permalink
[Feature] RegistrationNavGraph & RegistrationDestination 만들기 (#14)
Browse files Browse the repository at this point in the history
* [Feat]: RegistrationConstant 생성, NavGraph 기능 구현

* [Feat]: RegistrationViewModel 생성

* [Feat]: registrationNamingDestination 생성, Constant 작성

* [Feat]: registrationNaming UI 구현

* [Feat]: registrationNaming Model & State 생성

* [Feat]: registrationNaming Intent & Event 기능 구현

* [Feat]: RegistrationNamingScreen Sample Flow 구현

* [Feat]: route Destination 설정과 NavGraph 추가

* [Style]: 코드 포맷 수정

* [Fix]: 잘못된 파라미터 전달 수정

* [Refactor]: RegistrationNaming Intent & Event 재생성

* [Feat]: RegistrationCollecting Destination 생성, Constant 작성

* [Feat]: RegistrationCollecting Intent & Event 기능 구현

* [Feat]: RegistrationCollecting Model & State 생성

* [Feat]: RegistrationCollecting UI 기능 구현

* [Feat]: RegistrationCollecting NavGraph 연결

* [Style]: 코드 포맷 수정

* [Fix]: Preview 추가 & naming 수정

* [Fix] QA 후 수정
  • Loading branch information
jinuemong authored Jan 26, 2024
1 parent fd20656 commit 701a288
Show file tree
Hide file tree
Showing 20 changed files with 433 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ac.dnd.bookkeeping.android.presentation.common.theme.BookkeepingTheme
import ac.dnd.bookkeeping.android.presentation.common.util.makeRoute
import ac.dnd.bookkeeping.android.presentation.ui.main.home.homeDestination
import ac.dnd.bookkeeping.android.presentation.ui.main.login.loginNavGraph
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.registrationNavGraph
import ac.dnd.bookkeeping.android.presentation.ui.main.splash.SplashConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.splash.splashDestination
import androidx.compose.runtime.Composable
Expand All @@ -26,6 +27,7 @@ fun MainScreen(
)
) {
loginNavGraph(appState = appState)
registrationNavGraph(appState = appState)
homeDestination(appState = appState)
splashDestination(appState = appState)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration

object RegistrationConstant {
const val ROUTE = "/registration"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration

import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting.registrationCollectingDestination
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming.RegistrationNamingConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming.registrationNamingDestination
import androidx.navigation.NavGraphBuilder
import androidx.navigation.navigation

fun NavGraphBuilder.registrationNavGraph(
appState: ApplicationState
) {
navigation(
startDestination = RegistrationNamingConstant.ROUTE,
route = RegistrationConstant.ROUTE
) {
registrationNamingDestination(appState)
registrationCollectingDestination(appState)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration

import ac.dnd.bookkeeping.android.presentation.common.base.BaseViewModel
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class RegistrationViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle
): BaseViewModel()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

import ac.dnd.bookkeeping.android.presentation.ui.main.registration.RegistrationConstant

object RegistrationCollectingConstant {
const val ROUTE: String = "${RegistrationConstant.ROUTE}/collecting"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.RegistrationConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.RegistrationViewModel
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable

fun NavGraphBuilder.registrationCollectingDestination(
appState: ApplicationState
) {
composable(
route = RegistrationCollectingConstant.ROUTE
) { backStackEntry ->

val parentEntry = remember(backStackEntry) {
appState.navController.getBackStackEntry(RegistrationConstant.ROUTE)
}
val parentViewModel: RegistrationViewModel = hiltViewModel(parentEntry)
val viewModel: RegistrationCollectingViewModel = hiltViewModel()

val model: RegistrationCollectingModel = let {
val state by viewModel.state.collectAsStateWithLifecycle()
RegistrationCollectingModel(state = state)
}

ErrorObserver(viewModel)

RegistrationCollectingScreen(
appState = appState,
model = model,
event = viewModel.event,
intent = viewModel::onIntent,
handler = viewModel.handler
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

sealed interface RegistrationCollectingEvent {
data object GoToNextStep : RegistrationCollectingEvent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

sealed interface RegistrationCollectingIntent {
data object OnClickSubmit : RegistrationCollectingIntent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

data class RegistrationCollectingModel(
val state: RegistrationCollectingState,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

import ac.dnd.bookkeeping.android.presentation.common.util.LaunchedEffectWithLifecycle
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.EventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.MutableEventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.eventObserve
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.rememberApplicationState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.CoroutineExceptionHandler

@Composable
fun RegistrationCollectingScreen(
appState: ApplicationState,
model: RegistrationCollectingModel,
event: EventFlow<RegistrationCollectingEvent>,
intent: (RegistrationCollectingIntent) -> Unit,
handler: CoroutineExceptionHandler
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(color = Color.Black),
) {
Text(
text = "Collecting Screen",
fontSize = 20.sp,
color = Color.White,
modifier = Modifier.align(Alignment.Center)
)

Surface(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(30.dp)
.fillMaxWidth()
.clickable {
intent(RegistrationCollectingIntent.OnClickSubmit)
},
shape = RoundedCornerShape(10.dp),
color = Color.White
) {
Text(
text = "next",
fontSize = 20.sp,
color = Color.Black,
textAlign = TextAlign.Center,
modifier = Modifier.padding(5.dp)
)
}
}

LaunchedEffectWithLifecycle(event, handler) {
event.eventObserve { event ->
when (event) {
is RegistrationCollectingEvent.GoToNextStep -> {}
}
}
}
}

@Preview
@Composable
fun RegistrationCollectingScreenPreview() {
RegistrationCollectingScreen(
appState = rememberApplicationState(),
model = RegistrationCollectingModel(
state = RegistrationCollectingState.Init
),
event = MutableEventFlow(),
intent = {},
handler = CoroutineExceptionHandler { _, _ -> }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

sealed interface RegistrationCollectingState {
data object Init : RegistrationCollectingState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.collecting

import ac.dnd.bookkeeping.android.presentation.common.base.BaseViewModel
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.EventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.MutableEventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.asEventFlow
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject

@HiltViewModel
class RegistrationCollectingViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : BaseViewModel() {

private val _state: MutableStateFlow<RegistrationCollectingState> =
MutableStateFlow(RegistrationCollectingState.Init)
val state: StateFlow<RegistrationCollectingState> = _state.asStateFlow()

private val _event: MutableEventFlow<RegistrationCollectingEvent> = MutableEventFlow()
val event: EventFlow<RegistrationCollectingEvent> = _event.asEventFlow()

fun onIntent(intent: RegistrationCollectingIntent) {
when (intent) {
RegistrationCollectingIntent.OnClickSubmit -> goToNextStep()
}
}

private fun goToNextStep() {
launch {
_event.emit(RegistrationCollectingEvent.GoToNextStep)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming

import ac.dnd.bookkeeping.android.presentation.ui.main.registration.RegistrationConstant

object RegistrationNamingConstant {
const val ROUTE: String = "${RegistrationConstant.ROUTE}/naming"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming

import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.RegistrationConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.registration.RegistrationViewModel
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable

fun NavGraphBuilder.registrationNamingDestination(
appState: ApplicationState
) {
composable(
route = RegistrationNamingConstant.ROUTE
) { backStackEntry ->
val parentEntry = remember(backStackEntry) {
appState.navController.getBackStackEntry(RegistrationConstant.ROUTE)
}
val parentViewModel: RegistrationViewModel = hiltViewModel(parentEntry)
val viewModel: RegistrationNamingViewModel = hiltViewModel()

val model: RegistrationNamingModel = let {
val state by viewModel.state.collectAsStateWithLifecycle()
RegistrationNamingModel(state = state)
}

ErrorObserver(viewModel)

RegistrationNamingScreen(
appState = appState,
model = model,
event = viewModel.event,
intent = viewModel::onIntent,
handler = viewModel.handler
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming

sealed interface RegistrationNamingEvent {
data object GoToNextStep : RegistrationNamingEvent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming

sealed interface RegistrationNamingIntent {
data object OnClickSubmit : RegistrationNamingIntent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.registration.naming

data class RegistrationNamingModel(
val state: RegistrationNamingState,
)
Loading

0 comments on commit 701a288

Please sign in to comment.