Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
16 changes: 16 additions & 0 deletions app/src/main/java/com/threegap/bitnagil/MainNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import com.threegap.bitnagil.navigation.home.HomeNavHost
import com.threegap.bitnagil.presentation.emotion.EmotionScreenContainer
import com.threegap.bitnagil.presentation.guide.GuideScreenContainer
import com.threegap.bitnagil.presentation.login.LoginScreenContainer
import com.threegap.bitnagil.presentation.onboarding.OnBoardingScreenContainer
import com.threegap.bitnagil.presentation.onboarding.OnBoardingViewModel
Expand Down Expand Up @@ -112,6 +113,11 @@ fun MainNavHost(
),
)
},
navigateToGuide = {
navigator.navController.navigate(Route.Guide) {
launchSingleTop = true
}
},
navigateToRegisterRoutine = { routineId ->
navigator.navController.navigate(Route.WriteRoutine(routineId = routineId))
},
Expand Down Expand Up @@ -241,5 +247,15 @@ fun MainNavHost(
},
)
}

composable<Route.Guide> {
GuideScreenContainer(
navigateToBack = {
if (navigator.navController.previousBackStackEntry != null) {
navigator.navController.popBackStack()
}
},
)
}
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/threegap/bitnagil/Route.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ sealed interface Route {

@Serializable
data object Withdrawal : Route

@Serializable
data object Guide : Route
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ fun HomeNavHost(
navigateToOnBoarding: () -> Unit,
navigateToNotice: () -> Unit,
navigateToQnA: () -> Unit,
navigateToGuide: () -> Unit,
navigateToRegisterRoutine: (String?) -> Unit,
navigateToEmotion: () -> Unit,
) {
Expand All @@ -62,6 +63,7 @@ fun HomeNavHost(
) {
composable(HomeRoute.Home.route) {
HomeScreenContainer(
navigateToGuide = navigateToGuide,
navigateToRegisterRoutine = {
navigateToRegisterRoutine(null)
},
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions core/designsystem/src/main/res/drawable/ic_help_circle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"
android:pathData="M9.1,9.047C9.19,8.787 9.48,8.627 9.63,8.397C9.78,8.167 9.84,7.877 10.05,7.697C10.26,7.517 10.51,7.377 10.76,7.267C11.01,7.157 11.31,7.277 11.58,7.237C11.85,7.197 12.09,7.047 12.36,7.077C12.63,7.107 12.86,7.247 13.11,7.347C13.37,7.457 13.79,7.297 14.01,7.467C14.23,7.637 14.32,7.987 14.48,8.207C14.64,8.427 14.52,8.777 14.62,9.037C14.72,9.297 15.07,9.477 15.09,9.757C15.11,10.037 14.78,10.267 14.73,10.537C14.68,10.807 14.95,11.177 14.82,11.427C14.69,11.677 14.34,11.767 14.15,11.967C13.96,12.167 13.93,12.577 13.69,12.727C13.45,12.877 13.14,12.967 12.88,13.037C12.62,13.107 12.23,12.977 11.95,12.977C11.82,13.457 12.24,13.497 12.24,13.997M12.02,21.067C11.76,21.067 11.5,20.857 11.25,20.837C11,20.817 10.71,20.927 10.46,20.887C10.21,20.847 9.95,20.767 9.7,20.697C9.45,20.627 9.27,20.347 9.02,20.257C8.77,20.167 8.49,20.207 8.25,20.097C8.01,19.987 7.82,19.807 7.6,19.667C7.38,19.527 6.96,19.687 6.75,19.537C6.54,19.387 6.43,19.077 6.23,18.907C6.03,18.737 6.03,18.367 5.84,18.177C5.65,17.987 5.26,18.007 5.09,17.807C4.92,17.607 5.02,17.207 4.87,16.997C4.72,16.787 4.26,16.777 4.13,16.547C4,16.317 4.09,15.977 3.98,15.737C3.87,15.497 3.49,15.367 3.4,15.127C3.31,14.887 3.27,14.607 3.2,14.347C3.13,14.087 3.3,13.787 3.25,13.527C3.2,13.267 2.88,13.047 2.86,12.777C2.84,12.507 3.32,12.237 3.32,11.977C3.32,11.717 2.94,11.437 2.96,11.177C2.98,10.917 3.32,10.697 3.37,10.437C3.42,10.177 3.37,9.917 3.45,9.667C3.53,9.417 3.67,9.197 3.76,8.957C3.85,8.717 3.54,8.297 3.65,8.057C3.76,7.817 4.07,7.667 4.2,7.437C4.33,7.207 4.74,7.167 4.89,6.957C5.04,6.747 4.96,6.367 5.13,6.167C5.3,5.967 5.45,5.737 5.63,5.557C5.81,5.377 5.96,5.127 6.16,4.957C6.36,4.787 6.73,4.837 6.94,4.687C7.15,4.537 7.25,4.197 7.47,4.057C7.69,3.917 7.95,3.827 8.19,3.707C8.43,3.587 8.63,3.357 8.87,3.267C9.11,3.177 9.46,3.367 9.71,3.297C9.96,3.227 10.19,3.037 10.45,2.997C10.71,2.957 10.99,3.057 11.25,3.037C11.51,3.017 11.77,3.067 12.03,3.067C12.29,3.067 12.56,2.907 12.82,2.937C13.08,2.967 13.31,3.227 13.56,3.267C13.81,3.307 14.08,3.277 14.34,3.347C14.6,3.417 14.88,3.387 15.12,3.477C15.36,3.567 15.62,3.647 15.86,3.757C16.1,3.867 16.39,3.897 16.62,4.027C16.85,4.157 16.84,4.647 17.06,4.797C17.28,4.947 17.62,4.917 17.82,5.077C18.02,5.237 18.04,5.597 18.22,5.787C18.4,5.977 18.76,5.987 18.93,6.187C19.1,6.387 19.4,6.497 19.55,6.707C19.7,6.917 19.8,7.177 19.93,7.407C20.06,7.637 20.03,7.947 20.14,8.187C20.25,8.427 20.52,8.597 20.61,8.847C20.7,9.097 20.58,9.407 20.65,9.657C20.72,9.907 20.82,10.147 20.87,10.407C20.92,10.667 20.87,10.927 20.89,11.187C20.91,11.447 21.14,11.697 21.14,11.967C21.14,12.237 20.76,12.467 20.74,12.727C20.72,12.987 20.88,13.257 20.83,13.517C20.78,13.777 20.74,14.027 20.67,14.277C20.6,14.527 20.47,14.757 20.38,15.007C20.29,15.257 20.1,15.447 19.99,15.677C19.88,15.907 20.04,16.287 19.91,16.517C19.78,16.747 19.45,16.847 19.3,17.057C19.15,17.267 18.98,17.457 18.81,17.657C18.64,17.857 18.7,18.267 18.51,18.447C18.32,18.627 17.9,18.557 17.7,18.727C17.5,18.897 17.54,19.377 17.32,19.527C17.1,19.677 16.64,19.437 16.42,19.577C16.2,19.717 16.18,20.247 15.94,20.357C15.7,20.467 15.42,20.527 15.17,20.617C14.92,20.707 14.65,20.767 14.4,20.837C14.15,20.907 13.83,20.677 13.57,20.717C13.31,20.757 13.08,20.967 12.82,20.997C12.56,21.027 12.29,21.037 12.03,21.037L12.02,21.067ZM12.12,16.947C12.12,16.947 12.02,16.967 11.98,17.007C11.94,17.047 11.98,17.147 11.95,17.117C11.92,17.087 11.94,17.037 11.96,16.997C12.01,16.927 12.08,16.917 12.11,16.947H12.12Z"
android:strokeWidth="2"
android:strokeColor="#ffffff"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#ffffff"
android:pathData="M11.223,17.035a0.875,0.951 0,1 0,1.75 0a0.875,0.951 0,1 0,-1.75 0z" />
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.threegap.bitnagil.presentation.guide

import androidx.compose.foundation.background
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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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.threegap.bitnagil.designsystem.BitnagilTheme
import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar
import com.threegap.bitnagil.presentation.common.flow.collectAsEffect
import com.threegap.bitnagil.presentation.guide.component.atom.GuideButton
import com.threegap.bitnagil.presentation.guide.component.template.GuideBottomSheet
import com.threegap.bitnagil.presentation.guide.model.GuideIntent
import com.threegap.bitnagil.presentation.guide.model.GuideSideEffect
import com.threegap.bitnagil.presentation.guide.model.GuideType

@Composable
fun GuideScreenContainer(
navigateToBack: () -> Unit,
viewModel: GuideViewModel = hiltViewModel(),
) {
val uiState by viewModel.container.stateFlow.collectAsStateWithLifecycle()

viewModel.sideEffectFlow.collectAsEffect { sideEffect ->
when (sideEffect) {
is GuideSideEffect.NavigateToBack -> navigateToBack()
}
}

if (uiState.guideBottomSheetVisible) {
uiState.guideType?.let { guideType ->
GuideBottomSheet(
guideType = guideType,
onDismissRequest = { viewModel.sendIntent(GuideIntent.OnHideGuideBottomSheet) },
)
}
}

GuideScreen(
onClickGuideButton = { viewModel.sendIntent(GuideIntent.OnClickGuideButton(it)) },
onBackClick = { viewModel.sendIntent(GuideIntent.OnBackClick) },
)
}

@Composable
private fun GuideScreen(
onClickGuideButton: (GuideType) -> Unit,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
.fillMaxSize()
.background(BitnagilTheme.colors.white)
.statusBarsPadding(),
) {
BitnagilTopBar(
title = "설명서",
showBackButton = true,
onBackClick = onBackClick,
modifier = Modifier.fillMaxWidth(),
)

Spacer(modifier = Modifier.height(46.dp))

GuideType.entries.forEach { guideType ->
GuideButton(
title = guideType.title,
onClick = { onClickGuideButton(guideType) },
modifier = Modifier
.padding(horizontal = 16.dp)
.padding(bottom = 12.dp),
)
}
}
}

@Preview
@Composable
private fun GuideScreenPreview() {
GuideScreen(
onClickGuideButton = {},
onBackClick = {},
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.threegap.bitnagil.presentation.guide

import androidx.lifecycle.SavedStateHandle
import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel
import com.threegap.bitnagil.presentation.guide.model.GuideIntent
import com.threegap.bitnagil.presentation.guide.model.GuideSideEffect
import com.threegap.bitnagil.presentation.guide.model.GuideState
import dagger.hilt.android.lifecycle.HiltViewModel
import org.orbitmvi.orbit.syntax.simple.SimpleSyntax
import javax.inject.Inject

@HiltViewModel
class GuideViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
) : MviViewModel<GuideState, GuideSideEffect, GuideIntent>(
initState = GuideState(),
savedStateHandle = savedStateHandle,
) {
override suspend fun SimpleSyntax<GuideState, GuideSideEffect>.reduceState(
intent: GuideIntent,
state: GuideState,
): GuideState? {
val newState = when (intent) {
is GuideIntent.OnClickGuideButton -> {
state.copy(
guideType = intent.guideType,
guideBottomSheetVisible = true,
)
}

is GuideIntent.OnHideGuideBottomSheet -> {
state.copy(
guideType = null,
guideBottomSheetVisible = false,
)
}

is GuideIntent.OnBackClick -> {
sendSideEffect(GuideSideEffect.NavigateToBack)
null
}
}

return newState
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.threegap.bitnagil.presentation.guide.component.atom

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.threegap.bitnagil.designsystem.BitnagilTheme
import com.threegap.bitnagil.designsystem.R
import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon
import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple

@Composable
fun GuideButton(
title: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier
.background(
color = BitnagilTheme.colors.coolGray99,
shape = RoundedCornerShape(12.dp),
)
.fillMaxWidth()
.height(56.dp)
.clickableWithoutRipple { onClick() }
.padding(vertical = 14.dp, horizontal = 20.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
text = title,
color = BitnagilTheme.colors.coolGray10,
style = BitnagilTheme.typography.body2Medium,
)

BitnagilIcon(
id = R.drawable.ic_chevron_right_md,
tint = BitnagilTheme.colors.coolGray10,
)
}
}

@Preview
@Composable
private fun GuideButtonPreview() {
GuideButton(
title = "루틴 수정하기란?",
onClick = {},
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.threegap.bitnagil.presentation.guide.component.template

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.threegap.bitnagil.designsystem.BitnagilTheme
import com.threegap.bitnagil.presentation.guide.model.GuideType

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun GuideBottomSheet(
guideType: GuideType,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
) {
ModalBottomSheet(
onDismissRequest = onDismissRequest,
containerColor = BitnagilTheme.colors.coolGray99,
contentColor = BitnagilTheme.colors.coolGray99,
modifier = modifier,
) {
GuideBottomSheetContent(
guideType = guideType,
modifier = Modifier
.padding(horizontal = 24.dp)
.padding(bottom = 26.dp),
)
}
}

@Composable
private fun GuideBottomSheetContent(
guideType: GuideType,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier,
) {
Text(
text = guideType.title,
color = BitnagilTheme.colors.coolGray10,
style = BitnagilTheme.typography.title3SemiBold,
modifier = Modifier.padding(bottom = 10.dp),
)

Text(
text = guideType.description,
color = BitnagilTheme.colors.coolGray40,
style = BitnagilTheme.typography.body2Medium,
)

Spacer(modifier = Modifier.height(24.dp))

Image(
painter = painterResource(guideType.image),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(312f / 198f),
)
}
}

@Preview(showBackground = true)
@Composable
private fun GuideBottomSheetContentPreview() {
GuideBottomSheetContent(
guideType = GuideType.REGISTER,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.threegap.bitnagil.presentation.guide.model

import com.threegap.bitnagil.presentation.common.mviviewmodel.MviIntent

sealed class GuideIntent : MviIntent {
data object OnHideGuideBottomSheet : GuideIntent()
data object OnBackClick : GuideIntent()
data class OnClickGuideButton(val guideType: GuideType) : GuideIntent()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.threegap.bitnagil.presentation.guide.model

import com.threegap.bitnagil.presentation.common.mviviewmodel.MviSideEffect

sealed interface GuideSideEffect : MviSideEffect {
data object NavigateToBack : GuideSideEffect
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.threegap.bitnagil.presentation.guide.model

import com.threegap.bitnagil.presentation.common.mviviewmodel.MviState
import kotlinx.parcelize.Parcelize

@Parcelize
data class GuideState(
val guideType: GuideType? = null,
val guideBottomSheetVisible: Boolean = false,
) : MviState
Loading