From 060ced8eb388ac1eca88ec7124cb552691a0ab24 Mon Sep 17 00:00:00 2001 From: Ray Jang <48707913+ajou4095@users.noreply.github.com> Date: Wed, 7 Feb 2024 00:06:21 +0900 Subject: [PATCH] =?UTF-8?q?[Feature]=20Schedule=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/NotificationConstant.kt | 5 + .../notification/NotificationDestination.kt | 38 +++++ .../common/notification/NotificationEvent.kt | 3 + .../common/notification/NotificationIntent.kt | 3 + .../common/notification/NotificationModel.kt | 5 + .../common/notification/NotificationScreen.kt | 48 ++++++ .../common/notification/NotificationState.kt | 5 + .../notification/NotificationViewModel.kt | 29 ++++ .../relation/add/AddRelationConstant.kt | 2 +- .../relation/get/GetRelationConstant.kt | 2 +- .../ui/main/home/schedule/ScheduleConstant.kt | 5 + .../ui/main/home/schedule/ScheduleEvent.kt | 3 + .../ui/main/home/schedule/ScheduleIntent.kt | 3 + .../ui/main/home/schedule/ScheduleModel.kt | 5 + .../ui/main/home/schedule/ScheduleScreen.kt | 48 ++++++ .../ui/main/home/schedule/ScheduleState.kt | 5 + .../main/home/schedule/ScheduleViewModel.kt | 28 ++++ .../home/schedule/add/ScheduleAddConstant.kt | 7 + .../schedule/add/ScheduleAddDestination.kt | 38 +++++ .../home/schedule/add/ScheduleAddEvent.kt | 3 + .../home/schedule/add/ScheduleAddIntent.kt | 3 + .../home/schedule/add/ScheduleAddModel.kt | 5 + .../home/schedule/add/ScheduleAddScreen.kt | 48 ++++++ .../home/schedule/add/ScheduleAddState.kt | 5 + .../home/schedule/add/ScheduleAddViewModel.kt | 28 ++++ .../ScheduleAddNotificationEvent.kt | 3 + .../ScheduleAddNotificationIntent.kt | 3 + .../ScheduleAddNotificationModel.kt | 5 + .../ScheduleAddNotificationScreen.kt | 139 ++++++++++++++++++ .../ScheduleAddNotificationState.kt | 5 + .../ScheduleAddNotificationViewModel.kt | 29 ++++ .../add/repeat/ScheduleAddRepeatEvent.kt | 3 + .../add/repeat/ScheduleAddRepeatIntent.kt | 3 + .../add/repeat/ScheduleAddRepeatModel.kt | 5 + .../add/repeat/ScheduleAddRepeatScreen.kt | 139 ++++++++++++++++++ .../add/repeat/ScheduleAddRepeatState.kt | 5 + .../add/repeat/ScheduleAddRepeatViewModel.kt | 29 ++++ 37 files changed, 740 insertions(+), 2 deletions(-) create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationConstant.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationDestination.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationEvent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationIntent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationScreen.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationState.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationViewModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleConstant.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleEvent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleIntent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleScreen.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleState.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleViewModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddIntent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddState.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationEvent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationIntent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationScreen.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationState.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationViewModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatEvent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatIntent.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatModel.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatScreen.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatState.kt create mode 100644 presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatViewModel.kt diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationConstant.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationConstant.kt new file mode 100644 index 00000000..5e00f648 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationConstant.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +object NotificationConstant { + const val ROUTE: String = "/notification" +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationDestination.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationDestination.kt new file mode 100644 index 00000000..f37e8e3b --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationDestination.kt @@ -0,0 +1,38 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver +import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState +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.notificationDestination( + appState: ApplicationState +) { + composable( + route = NotificationConstant.ROUTE + ) { + val viewModel: NotificationViewModel = hiltViewModel() + + val model: NotificationModel = let { + val state by viewModel.state.collectAsStateWithLifecycle() + + NotificationModel( + state = state + ) + } + + ErrorObserver(viewModel) + + NotificationScreen( + appState = appState, + model = model, + event = viewModel.event, + intent = viewModel::onIntent, + handler = viewModel.handler + ) + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationEvent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationEvent.kt new file mode 100644 index 00000000..360f540e --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationEvent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +sealed interface NotificationEvent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationIntent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationIntent.kt new file mode 100644 index 00000000..e0b13dd5 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationIntent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +sealed interface NotificationIntent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationModel.kt new file mode 100644 index 00000000..ba8eab57 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationModel.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +data class NotificationModel( + val state: NotificationState, +) diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationScreen.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationScreen.kt new file mode 100644 index 00000000..1d2dc8ca --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationScreen.kt @@ -0,0 +1,48 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +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.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.tooling.preview.Preview +import kotlinx.coroutines.CoroutineExceptionHandler + +@Composable +fun NotificationScreen( + appState: ApplicationState, + model: NotificationModel, + event: EventFlow, + intent: (NotificationIntent) -> Unit, + handler: CoroutineExceptionHandler +) { + val scope = rememberCoroutineScope() + + Box { + + } + + LaunchedEffectWithLifecycle(event, handler) { + event.eventObserve { event -> + + } + } +} + +@Preview +@Composable +fun NotificationScreenPreview() { + NotificationScreen( + appState = rememberApplicationState(), + model = NotificationModel( + state = NotificationState.Init + ), + event = MutableEventFlow(), + intent = {}, + handler = CoroutineExceptionHandler { _, _ -> } + ) +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationState.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationState.kt new file mode 100644 index 00000000..2995c5fa --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationState.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +sealed interface NotificationState { + data object Init : NotificationState +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationViewModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationViewModel.kt new file mode 100644 index 00000000..df0da1a6 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/notification/NotificationViewModel.kt @@ -0,0 +1,29 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.notification + +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 NotificationViewModel @Inject constructor( + private val savedStateHandle: SavedStateHandle, +) : BaseViewModel() { + + private val _state: MutableStateFlow = + MutableStateFlow(NotificationState.Init) + val state: StateFlow = _state.asStateFlow() + + private val _event: MutableEventFlow = MutableEventFlow() + val event: EventFlow = _event.asEventFlow() + + fun onIntent(intent: NotificationIntent) { + + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/add/AddRelationConstant.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/add/AddRelationConstant.kt index 8d1b4ca1..519a95e6 100644 --- a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/add/AddRelationConstant.kt +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/add/AddRelationConstant.kt @@ -1,7 +1,7 @@ package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.relation.add object AddRelationConstant { - const val ROUTE: String = "addName" + const val ROUTE: String = "/addName" const val ROUTE_ARGUMENT_MODEL = "relation" const val CONTAIN_RELATION = "${ROUTE}/{${ROUTE_ARGUMENT_MODEL}}" diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/get/GetRelationConstant.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/get/GetRelationConstant.kt index 484bd3fb..3efc425b 100644 --- a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/get/GetRelationConstant.kt +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/common/relation/get/GetRelationConstant.kt @@ -1,5 +1,5 @@ package ac.dnd.bookkeeping.android.presentation.ui.main.home.common.relation.get object GetRelationConstant { - const val ROUTE: String = "searchName" + const val ROUTE: String = "/searchName" } diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleConstant.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleConstant.kt new file mode 100644 index 00000000..b12ca771 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleConstant.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +object ScheduleConstant { + const val ROUTE: String = "/schedule" +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleEvent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleEvent.kt new file mode 100644 index 00000000..dd550c6a --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleEvent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +sealed interface ScheduleEvent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleIntent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleIntent.kt new file mode 100644 index 00000000..bab71e2b --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleIntent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +sealed interface ScheduleIntent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleModel.kt new file mode 100644 index 00000000..b3088bb1 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleModel.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +data class ScheduleModel( + val state: ScheduleState, +) diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleScreen.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleScreen.kt new file mode 100644 index 00000000..e0ea9d37 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleScreen.kt @@ -0,0 +1,48 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +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.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.tooling.preview.Preview +import kotlinx.coroutines.CoroutineExceptionHandler + +@Composable +fun ScheduleScreen( + appState: ApplicationState, + model: ScheduleModel, + event: EventFlow, + intent: (ScheduleIntent) -> Unit, + handler: CoroutineExceptionHandler +) { + val scope = rememberCoroutineScope() + + Box { + + } + + LaunchedEffectWithLifecycle(event, handler) { + event.eventObserve { event -> + + } + } +} + +@Preview +@Composable +fun ScheduleScreenPreview() { + ScheduleScreen( + appState = rememberApplicationState(), + model = ScheduleModel( + state = ScheduleState.Init + ), + event = MutableEventFlow(), + intent = {}, + handler = CoroutineExceptionHandler { _, _ -> } + ) +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleState.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleState.kt new file mode 100644 index 00000000..de09e49a --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleState.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +sealed interface ScheduleState { + data object Init : ScheduleState +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleViewModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleViewModel.kt new file mode 100644 index 00000000..c8817c4e --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/ScheduleViewModel.kt @@ -0,0 +1,28 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule + +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 ScheduleViewModel @Inject constructor( + private val savedStateHandle: SavedStateHandle, +) : BaseViewModel() { + + private val _state: MutableStateFlow = MutableStateFlow(ScheduleState.Init) + val state: StateFlow = _state.asStateFlow() + + private val _event: MutableEventFlow = MutableEventFlow() + val event: EventFlow = _event.asEventFlow() + + fun onIntent(intent: ScheduleIntent) { + + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt new file mode 100644 index 00000000..c05e0cd3 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt @@ -0,0 +1,7 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +import ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.ScheduleConstant + +object ScheduleAddConstant { + const val ROUTE: String = "${ScheduleConstant.ROUTE}/add" +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt new file mode 100644 index 00000000..ec2bbc48 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt @@ -0,0 +1,38 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver +import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState +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.scheduleAddDestination( + appState: ApplicationState +) { + composable( + route = ScheduleAddConstant.ROUTE + ) { + val viewModel: ScheduleAddViewModel = hiltViewModel() + + val model: ScheduleAddModel = let { + val state by viewModel.state.collectAsStateWithLifecycle() + + ScheduleAddModel( + state = state + ) + } + + ErrorObserver(viewModel) + + ScheduleAddScreen( + appState = appState, + model = model, + event = viewModel.event, + intent = viewModel::onIntent, + handler = viewModel.handler + ) + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt new file mode 100644 index 00000000..6437a2c8 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +sealed interface ScheduleAddEvent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddIntent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddIntent.kt new file mode 100644 index 00000000..ba892607 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddIntent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +sealed interface ScheduleAddIntent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddModel.kt new file mode 100644 index 00000000..4ac42b45 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddModel.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +data class ScheduleAddModel( + val state: ScheduleAddState, +) diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt new file mode 100644 index 00000000..002c9766 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt @@ -0,0 +1,48 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +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.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.tooling.preview.Preview +import kotlinx.coroutines.CoroutineExceptionHandler + +@Composable +fun ScheduleAddScreen( + appState: ApplicationState, + model: ScheduleAddModel, + event: EventFlow, + intent: (ScheduleAddIntent) -> Unit, + handler: CoroutineExceptionHandler +) { + val scope = rememberCoroutineScope() + + Box { + + } + + LaunchedEffectWithLifecycle(event, handler) { + event.eventObserve { event -> + + } + } +} + +@Preview +@Composable +fun ScheduleAddScreenPreview() { + ScheduleAddScreen( + appState = rememberApplicationState(), + model = ScheduleAddModel( + state = ScheduleAddState.Init + ), + event = MutableEventFlow(), + intent = {}, + handler = CoroutineExceptionHandler { _, _ -> } + ) +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddState.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddState.kt new file mode 100644 index 00000000..847f0a09 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddState.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +sealed interface ScheduleAddState { + data object Init : ScheduleAddState +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt new file mode 100644 index 00000000..d1c8cbe2 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt @@ -0,0 +1,28 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add + +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 ScheduleAddViewModel @Inject constructor( + private val savedStateHandle: SavedStateHandle, +) : BaseViewModel() { + + private val _state: MutableStateFlow = MutableStateFlow(ScheduleAddState.Init) + val state: StateFlow = _state.asStateFlow() + + private val _event: MutableEventFlow = MutableEventFlow() + val event: EventFlow = _event.asEventFlow() + + fun onIntent(intent: ScheduleAddIntent) { + + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationEvent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationEvent.kt new file mode 100644 index 00000000..e59bc608 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationEvent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.notification + +sealed interface ScheduleAddNotificationEvent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationIntent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationIntent.kt new file mode 100644 index 00000000..bdd7f2bc --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationIntent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.notification + +sealed interface ScheduleAddNotificationIntent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationModel.kt new file mode 100644 index 00000000..ed97dc8e --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationModel.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.notification + +data class ScheduleAddNotificationModel( + val state: ScheduleAddNotificationState, +) diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationScreen.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationScreen.kt new file mode 100644 index 00000000..283114ef --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationScreen.kt @@ -0,0 +1,139 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.notification + +import ac.dnd.bookkeeping.android.presentation.common.theme.Gray200 +import ac.dnd.bookkeeping.android.presentation.common.theme.Headline2 +import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver +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.common.view.BottomSheetScreen +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButton +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButtonProperties +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButtonSize +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButtonType +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.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.holix.android.bottomsheetdialog.compose.BottomSheetBehaviorProperties +import com.holix.android.bottomsheetdialog.compose.BottomSheetDialogProperties +import kotlinx.coroutines.CoroutineExceptionHandler + +@Composable +fun ScheduleAddNotificationScreen( + appState: ApplicationState, + onDismissRequest: () -> Unit, + onResult: () -> Unit, + viewModel: ScheduleAddNotificationViewModel = hiltViewModel() +) { + val model: ScheduleAddNotificationModel = Unit.let { + val state by viewModel.state.collectAsStateWithLifecycle() + + ScheduleAddNotificationModel( + state = state + ) + } + ErrorObserver(viewModel) + + ScheduleAddNotificationScreen( + appState = appState, + model = model, + event = viewModel.event, + intent = viewModel::onIntent, + handler = viewModel.handler, + onDismissRequest = onDismissRequest, + onResult = onResult + ) +} + +@Composable +private fun ScheduleAddNotificationScreen( + appState: ApplicationState, + model: ScheduleAddNotificationModel, + event: EventFlow, + intent: (ScheduleAddNotificationIntent) -> Unit, + handler: CoroutineExceptionHandler, + onDismissRequest: () -> Unit, + onResult: () -> Unit, +) { + val scope = rememberCoroutineScope() + + BottomSheetScreen( + onDismissRequest = onDismissRequest, + properties = BottomSheetDialogProperties( + behaviorProperties = BottomSheetBehaviorProperties( + state = BottomSheetBehaviorProperties.State.Expanded, + skipCollapsed = true + ) + ) + ) { + Column( + modifier = Modifier + .wrapContentHeight() + .background(Gray200) + .padding(20.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Center + ) { + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "", + style = Headline2 + ) + Spacer(modifier = Modifier.height(10.dp)) + ConfirmButton( + modifier = Modifier.fillMaxWidth(), + properties = ConfirmButtonProperties( + size = ConfirmButtonSize.Xlarge, + type = ConfirmButtonType.Primary + ), + onClick = { + onResult() + } + ) { style -> + Text( + text = "확인", + style = style + ) + } + Spacer(modifier = Modifier.height(10.dp)) + } + } + + LaunchedEffectWithLifecycle(event, handler) { + event.eventObserve { event -> + + } + } +} + +@Preview(apiLevel = 33) +@Composable +private fun ScheduleAddNotificationScreenPreview() { + ScheduleAddNotificationScreen( + appState = rememberApplicationState(), + model = ScheduleAddNotificationModel(state = ScheduleAddNotificationState.Init), + event = MutableEventFlow(), + intent = {}, + handler = CoroutineExceptionHandler { _, _ -> }, + onDismissRequest = {}, + onResult = {} + ) +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationState.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationState.kt new file mode 100644 index 00000000..f3f35bbd --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationState.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.notification + +sealed interface ScheduleAddNotificationState { + data object Init : ScheduleAddNotificationState +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationViewModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationViewModel.kt new file mode 100644 index 00000000..61d69776 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/notification/ScheduleAddNotificationViewModel.kt @@ -0,0 +1,29 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.notification + +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 ScheduleAddNotificationViewModel @Inject constructor( + private val savedStateHandle: SavedStateHandle, +) : BaseViewModel() { + + private val _state: MutableStateFlow = + MutableStateFlow(ScheduleAddNotificationState.Init) + val state: StateFlow = _state.asStateFlow() + + private val _event: MutableEventFlow = MutableEventFlow() + val event: EventFlow = _event.asEventFlow() + + fun onIntent(intent: ScheduleAddNotificationIntent) { + + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatEvent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatEvent.kt new file mode 100644 index 00000000..b2fbb6e9 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatEvent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.repeat + +sealed interface ScheduleAddRepeatEvent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatIntent.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatIntent.kt new file mode 100644 index 00000000..4b3ad9a4 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatIntent.kt @@ -0,0 +1,3 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.repeat + +sealed interface ScheduleAddRepeatIntent diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatModel.kt new file mode 100644 index 00000000..3cb666ee --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatModel.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.repeat + +data class ScheduleAddRepeatModel( + val state: ScheduleAddRepeatState, +) diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatScreen.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatScreen.kt new file mode 100644 index 00000000..adf10ad4 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatScreen.kt @@ -0,0 +1,139 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.repeat + +import ac.dnd.bookkeeping.android.presentation.common.theme.Gray200 +import ac.dnd.bookkeeping.android.presentation.common.theme.Headline2 +import ac.dnd.bookkeeping.android.presentation.common.util.ErrorObserver +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.common.view.BottomSheetScreen +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButton +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButtonProperties +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButtonSize +import ac.dnd.bookkeeping.android.presentation.common.view.confirm.ConfirmButtonType +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.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.holix.android.bottomsheetdialog.compose.BottomSheetBehaviorProperties +import com.holix.android.bottomsheetdialog.compose.BottomSheetDialogProperties +import kotlinx.coroutines.CoroutineExceptionHandler + +@Composable +fun ScheduleAddRepeatScreen( + appState: ApplicationState, + onDismissRequest: () -> Unit, + onResult: () -> Unit, + viewModel: ScheduleAddRepeatViewModel = hiltViewModel() +) { + val model: ScheduleAddRepeatModel = Unit.let { + val state by viewModel.state.collectAsStateWithLifecycle() + + ScheduleAddRepeatModel( + state = state + ) + } + ErrorObserver(viewModel) + + ScheduleAddRepeatScreen( + appState = appState, + model = model, + event = viewModel.event, + intent = viewModel::onIntent, + handler = viewModel.handler, + onDismissRequest = onDismissRequest, + onResult = onResult + ) +} + +@Composable +private fun ScheduleAddRepeatScreen( + appState: ApplicationState, + model: ScheduleAddRepeatModel, + event: EventFlow, + intent: (ScheduleAddRepeatIntent) -> Unit, + handler: CoroutineExceptionHandler, + onDismissRequest: () -> Unit, + onResult: () -> Unit, +) { + val scope = rememberCoroutineScope() + + BottomSheetScreen( + onDismissRequest = onDismissRequest, + properties = BottomSheetDialogProperties( + behaviorProperties = BottomSheetBehaviorProperties( + state = BottomSheetBehaviorProperties.State.Expanded, + skipCollapsed = true + ) + ) + ) { + Column( + modifier = Modifier + .wrapContentHeight() + .background(Gray200) + .padding(20.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Center + ) { + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "", + style = Headline2 + ) + Spacer(modifier = Modifier.height(10.dp)) + ConfirmButton( + modifier = Modifier.fillMaxWidth(), + properties = ConfirmButtonProperties( + size = ConfirmButtonSize.Xlarge, + type = ConfirmButtonType.Primary + ), + onClick = { + onResult() + } + ) { style -> + Text( + text = "확인", + style = style + ) + } + Spacer(modifier = Modifier.height(10.dp)) + } + } + + LaunchedEffectWithLifecycle(event, handler) { + event.eventObserve { event -> + + } + } +} + +@Preview(apiLevel = 33) +@Composable +private fun ScheduleAddRepeatScreenPreview() { + ScheduleAddRepeatScreen( + appState = rememberApplicationState(), + model = ScheduleAddRepeatModel(state = ScheduleAddRepeatState.Init), + event = MutableEventFlow(), + intent = {}, + handler = CoroutineExceptionHandler { _, _ -> }, + onDismissRequest = {}, + onResult = {} + ) +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatState.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatState.kt new file mode 100644 index 00000000..9c1c1ede --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatState.kt @@ -0,0 +1,5 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.repeat + +sealed interface ScheduleAddRepeatState { + data object Init : ScheduleAddRepeatState +} diff --git a/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatViewModel.kt b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatViewModel.kt new file mode 100644 index 00000000..cd799bf9 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/bookkeeping/android/presentation/ui/main/home/schedule/add/repeat/ScheduleAddRepeatViewModel.kt @@ -0,0 +1,29 @@ +package ac.dnd.bookkeeping.android.presentation.ui.main.home.schedule.add.repeat + +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 ScheduleAddRepeatViewModel @Inject constructor( + private val savedStateHandle: SavedStateHandle, +) : BaseViewModel() { + + private val _state: MutableStateFlow = + MutableStateFlow(ScheduleAddRepeatState.Init) + val state: StateFlow = _state.asStateFlow() + + private val _event: MutableEventFlow = MutableEventFlow() + val event: EventFlow = _event.asEventFlow() + + fun onIntent(intent: ScheduleAddRepeatIntent) { + + } +}