diff --git a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt index d9d7d227..623a6c72 100644 --- a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt +++ b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt @@ -3,17 +3,28 @@ package com.threegap.bitnagil.navigation.home import android.annotation.SuppressLint import android.app.Activity import androidx.activity.compose.BackHandler +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.R +import com.threegap.bitnagil.designsystem.component.atom.BitnagilFloatingActionMenu +import com.threegap.bitnagil.designsystem.component.atom.FloatingActionItem +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.home.HomeScreenContainer import com.threegap.bitnagil.presentation.mypage.MyPageScreenContainer import com.threegap.bitnagil.presentation.recommendroutine.RecommendRoutineScreenContainer @@ -31,48 +42,83 @@ fun HomeNavHost( navigateToEmotion: () -> Unit, ) { val navigator = rememberHomeNavigator() + var showFloatingOverlay by remember { mutableStateOf(false) } DoubleBackButtonPressedHandler() - Scaffold( - modifier = Modifier.fillMaxSize(), - bottomBar = { - HomeBottomNavigationBar(navController = navigator.navController) - }, - content = { _ -> - NavHost( - navController = navigator.navController, - startDestination = navigator.startDestination, - modifier = modifier, - ) { - composable(HomeRoute.Home.route) { - HomeScreenContainer( - navigateToRegisterRoutine = { - navigateToRegisterRoutine(null) - }, - navigateToEditRoutine = navigateToEditRoutine, - navigateToEmotion = navigateToEmotion, - ) - } + Box(modifier = Modifier.fillMaxSize()) { + Scaffold( + modifier = Modifier.fillMaxSize(), + bottomBar = { + HomeBottomNavigationBar(navController = navigator.navController) + }, + content = { _ -> + NavHost( + navController = navigator.navController, + startDestination = navigator.startDestination, + modifier = modifier, + ) { + composable(HomeRoute.Home.route) { + HomeScreenContainer( + navigateToRegisterRoutine = { + navigateToRegisterRoutine(null) + }, + navigateToEditRoutine = navigateToEditRoutine, + navigateToEmotion = navigateToEmotion, + ) + } - composable(HomeRoute.RecommendRoutine.route) { - RecommendRoutineScreenContainer( - navigateToEmotion = navigateToEmotion, - navigateToRegisterRoutine = navigateToRegisterRoutine, - ) - } + composable(HomeRoute.RecommendRoutine.route) { + RecommendRoutineScreenContainer( + navigateToEmotion = navigateToEmotion, + navigateToRegisterRoutine = navigateToRegisterRoutine, + ) + } - composable(HomeRoute.MyPage.route) { - MyPageScreenContainer( - navigateToSetting = navigateToSetting, - navigateToOnBoarding = navigateToOnBoarding, - navigateToNotice = navigateToNotice, - navigateToQnA = navigateToQnA, - ) + composable(HomeRoute.MyPage.route) { + MyPageScreenContainer( + navigateToSetting = navigateToSetting, + navigateToOnBoarding = navigateToOnBoarding, + navigateToNotice = navigateToNotice, + navigateToQnA = navigateToQnA, + ) + } } + }, + ) + + if (navigator.shouldShowFloatingAction()) { + if (showFloatingOverlay) { + Box( + modifier = Modifier + .fillMaxSize() + .background(BitnagilTheme.colors.black.copy(alpha = 0.7f)) + .clickableWithoutRipple { showFloatingOverlay = false }, + ) } - }, - ) + + BitnagilFloatingActionMenu( + actions = listOf( + FloatingActionItem( + icon = R.drawable.ic_report, + text = "제보하기", + onClick = {}, + ), + FloatingActionItem( + icon = R.drawable.ic_add_routine, + text = "루틴 등록", + onClick = { navigateToRegisterRoutine(null) }, + ), + ), + isExpanded = showFloatingOverlay, + onToggle = { expanded -> showFloatingOverlay = expanded }, + modifier = Modifier + .align(Alignment.BottomEnd) + .padding(16.dp) + .padding(bottom = 80.dp), + ) + } + } } @Composable diff --git a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt index 0d6260fe..319eaf88 100644 --- a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt +++ b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt @@ -3,12 +3,24 @@ package com.threegap.bitnagil.navigation.home import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.navigation.NavHostController +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController class HomeNavigator( val navController: NavHostController, ) { val startDestination = HomeRoute.Home.route + + @Composable + fun getCurrentRoute(): String? { + return navController.currentBackStackEntryAsState().value?.destination?.route + } + + @Composable + fun shouldShowFloatingAction(): Boolean { + val currentRoute = getCurrentRoute() + return currentRoute == HomeRoute.Home.route || currentRoute == HomeRoute.RecommendRoutine.route + } } @Composable diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/BitnagilColors.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/BitnagilColors.kt index 96ea176f..e76304cd 100644 --- a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/BitnagilColors.kt +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/BitnagilColors.kt @@ -15,6 +15,10 @@ data class BitnagilColors( val emotionLonely: Color = EmotionLonely, val emotionSad: Color = EmotionSad, val emotionAnxiety: Color = EmotionAnxiety, + val progressBarGradientStartColor: Color = ProgressBarGradientStartColor, + val progressBarGradientEndColor: Color = ProgressBarGradientEndColor, + val homeGradientStartColor: Color = HomeGradientStartColor, + val homeGradientEndColor: Color = HomeGradientEndColor, val coolGray99: Color = CoolGray99, val coolGray98: Color = CoolGray98, val coolGray97: Color = CoolGray97, diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/Color.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/Color.kt index 349c184c..d15bf814 100644 --- a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/Color.kt +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/color/Color.kt @@ -11,6 +11,10 @@ val EmotionLethargy = Color(0xFFFFC0A1) val EmotionLonely = Color(0xFFC8C1DE) val EmotionSad = Color(0xFFA9B9FF) val EmotionAnxiety = Color(0xFF96D8AD) +val ProgressBarGradientStartColor = Color(0xFFA9CFFF) +val ProgressBarGradientEndColor = Color(0xFFFFCDB3) +val HomeGradientStartColor = Color(0xFFFFEADF) +val HomeGradientEndColor = Color(0xFFF0F7FF) val CoolGray99 = Color(0xFFF7F7F8) val CoolGray98 = Color(0xFFF4F4F5) @@ -26,7 +30,7 @@ val CoolGray40 = Color(0xFF5A5C63) val CoolGray30 = Color(0xFF46474C) val CoolGray20 = Color(0xFF292A2D) val CoolGray10 = Color(0xFF171719) -val CoolGray7 = Color(0xFF0F0F10) +val CoolGray7 = Color(0xFF141415) val CoolGray5 = Color(0xFF0F0F10) val Navy900 = Color(0xFF050B1B) diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilCheckBox.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilCheckBox.kt new file mode 100644 index 00000000..1aef8907 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilCheckBox.kt @@ -0,0 +1,79 @@ +package com.threegap.bitnagil.designsystem.component.atom + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +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.modifier.clickableWithoutRipple + +@Composable +fun BitnagilCheckBox( + checked: Boolean, + modifier: Modifier = Modifier, + onCheckedChange: ((Boolean) -> Unit)? = null, + colors: BitnagilCheckBoxColor = BitnagilCheckBoxColor.terms(), +) { + val iconColor = if (checked) colors.checkedColor else colors.uncheckedColor + + Box( + modifier = modifier + .let { + if (onCheckedChange != null) { + it.clickableWithoutRipple { onCheckedChange(!checked) } + } else { + it + } + } + .background( + color = BitnagilTheme.colors.white, + shape = RoundedCornerShape(6.dp), + ), + contentAlignment = Alignment.Center, + ) { + Image( + imageVector = ImageVector.vectorResource(R.drawable.ic_check), + contentDescription = null, + colorFilter = ColorFilter.tint(iconColor), + modifier = modifier.size(24.dp), + ) + } +} + +data class BitnagilCheckBoxColor( + val uncheckedColor: Color, + val checkedColor: Color, +) { + companion object { + @Composable + fun terms(): BitnagilCheckBoxColor = BitnagilCheckBoxColor( + uncheckedColor = BitnagilTheme.colors.navy50, + checkedColor = BitnagilTheme.colors.navy500, + ) + } +} + +@Preview +@Composable +private fun BitnagilCheckBoxPreview() { + var checked by remember { mutableStateOf(false) } + BitnagilCheckBox( + checked = checked, + onCheckedChange = { checked = !checked }, + ) +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilFloatingButton.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilFloatingButton.kt new file mode 100644 index 00000000..01ea584a --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilFloatingButton.kt @@ -0,0 +1,198 @@ +package com.threegap.bitnagil.designsystem.component.atom + +import androidx.annotation.DrawableRes +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +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.modifier.clickableWithoutRipple + +@Composable +fun BitnagilFloatingButton( + @DrawableRes id: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Box( + contentAlignment = Alignment.Center, + modifier = modifier + .background( + color = BitnagilTheme.colors.navy500, + shape = CircleShape, + ) + .size(52.dp) + .clickableWithoutRipple { onClick() }, + ) { + Image( + imageVector = ImageVector.vectorResource(id), + contentDescription = null, + colorFilter = ColorFilter.tint(BitnagilTheme.colors.white), + modifier = Modifier.size(24.dp), + ) + } +} + +@Composable +fun BitnagilFloatingActionMenu( + actions: List, + isExpanded: Boolean, + onToggle: (Boolean) -> Unit, + modifier: Modifier = Modifier, + @DrawableRes defaultIcon: Int = R.drawable.ic_plus, + @DrawableRes activeIcon: Int = R.drawable.ic_close, +) { + Box(modifier = modifier) { + AnimatedVisibility( + visible = isExpanded && actions.isNotEmpty(), + enter = slideInVertically( + initialOffsetY = { it / 2 }, + animationSpec = tween(durationMillis = 300), + ) + fadeIn( + animationSpec = tween(durationMillis = 300), + ) + scaleIn( + initialScale = 0.8f, + animationSpec = tween(durationMillis = 300), + ), + exit = slideOutVertically( + targetOffsetY = { it / 2 }, + animationSpec = tween(durationMillis = 200), + ) + fadeOut( + animationSpec = tween(durationMillis = 200), + ) + scaleOut( + targetScale = 0.8f, + animationSpec = tween(durationMillis = 200), + ), + modifier = Modifier + .align(Alignment.BottomEnd) + .padding(bottom = 67.dp), + ) { + Column( + modifier = Modifier + .background( + color = BitnagilTheme.colors.white, + shape = RoundedCornerShape(12.dp), + ), + ) { + Column( + modifier = Modifier.padding(vertical = 16.dp, horizontal = 22.dp), + verticalArrangement = Arrangement.spacedBy(24.dp), + ) { + actions.forEach { action -> + FloatingActionMenuItem( + icon = action.icon, + text = action.text, + onClick = { + action.onClick() + onToggle(false) + }, + ) + } + } + } + } + + Box( + modifier = Modifier.align(Alignment.BottomEnd), + ) { + BitnagilFloatingButton( + id = if (isExpanded) activeIcon else defaultIcon, + onClick = { onToggle(!isExpanded) }, + ) + } + } +} + +data class FloatingActionItem( + @DrawableRes val icon: Int, + val text: String, + val onClick: () -> Unit, +) + +@Composable +private fun FloatingActionMenuItem( + @DrawableRes icon: Int, + text: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val scale by animateFloatAsState( + targetValue = 1f, + animationSpec = tween(durationMillis = 200), + label = "menu_item_scale", + ) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(14.dp), + modifier = modifier + .scale(scale) + .clickableWithoutRipple { onClick() }, + ) { + BitnagilIcon( + id = icon, + tint = null, + ) + + Text( + text = text, + style = BitnagilTheme.typography.subtitle1Medium, + color = BitnagilTheme.colors.navy500, + ) + } +} + +@Preview +@Composable +private fun BitnagilFloatingButtonPreview() { + Column { + BitnagilFloatingButton( + id = R.drawable.ic_plus, + onClick = {}, + ) + + BitnagilFloatingActionMenu( + actions = listOf( + FloatingActionItem( + icon = R.drawable.ic_report, + text = "제보하기", + onClick = {}, + ), + FloatingActionItem( + icon = R.drawable.ic_add_routine, + text = "루틴 등록", + onClick = {}, + ), + ), + isExpanded = true, + onToggle = {}, + ) + } +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt new file mode 100644 index 00000000..7dd4ca02 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt @@ -0,0 +1,66 @@ +package com.threegap.bitnagil.designsystem.component.atom + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +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.graphics.ColorFilter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +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.modifier.clickableWithoutRipple + +@Composable +fun BitnagilIcon( + @DrawableRes id: Int, + modifier: Modifier = Modifier, + tint: Color? = BitnagilTheme.colors.black, +) { + Image( + imageVector = ImageVector.vectorResource(id), + contentDescription = null, + colorFilter = tint?.let { ColorFilter.tint(it) }, + modifier = modifier, + ) +} + +@Composable +fun BitnagilIconButton( + @DrawableRes id: Int, + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + paddingValues: PaddingValues = PaddingValues(0.dp), + tint: Color? = BitnagilTheme.colors.black, +) { + Box( + modifier = modifier + .clickableWithoutRipple( + enabled = enabled, + onClick = onClick, + ) + .padding(paddingValues), + contentAlignment = Alignment.Center, + ) { + BitnagilIcon( + id = id, + tint = tint, + ) + } +} + +@Preview +@Composable +private fun BitnagilIconPreview() { + BitnagilIcon( + id = R.drawable.ic_back_arrow_20, + ) +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilProgressBar.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilProgressBar.kt new file mode 100644 index 00000000..69af8875 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilProgressBar.kt @@ -0,0 +1,124 @@ +package com.threegap.bitnagil.designsystem.component.atom + +import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +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.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.threegap.bitnagil.designsystem.BitnagilTheme + +@Composable +fun BitnagilProgressBar( + progress: Float, + modifier: Modifier = Modifier, + color: BitnagilProgressBarColor = BitnagilProgressBarColor.default(), + height: Dp = 5.dp, +) { + val animatedProgress by animateFloatAsState( + targetValue = progress.coerceIn(0f, 1f), + label = "ProgressBarAnimation", + animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing), + ) + + Canvas( + modifier = modifier + .fillMaxWidth() + .height(height), + ) { + val strokeWidth = size.height + + drawLine( + color = color.backgroundColor, + start = Offset(0f, size.height / 2), + end = Offset(size.width, size.height / 2), + strokeWidth = strokeWidth, + cap = StrokeCap.Round, + ) + + if (animatedProgress > 0) { + val progressEndX = size.width * animatedProgress + drawLine( + brush = Brush.horizontalGradient( + colors = listOf(color.gradientStartColor, color.gradientEndColor), + startX = 0f, + endX = progressEndX, + ), + start = Offset(0f, size.height / 2), + end = Offset(progressEndX, size.height / 2), + strokeWidth = strokeWidth, + cap = StrokeCap.Round, + ) + } + } +} + +@Immutable +data class BitnagilProgressBarColor( + val gradientStartColor: Color, + val gradientEndColor: Color, + val backgroundColor: Color, +) { + companion object { + @Composable + fun default(): BitnagilProgressBarColor = BitnagilProgressBarColor( + gradientStartColor = BitnagilTheme.colors.progressBarGradientStartColor, + gradientEndColor = BitnagilTheme.colors.progressBarGradientEndColor, + backgroundColor = BitnagilTheme.colors.white, + ) + } +} + +@Preview +@Composable +private fun BitnagilProgressBarPreview() { + var progress by remember { mutableFloatStateOf(0.0f) } + + Column { + BitnagilProgressBar( + progress = progress, + modifier = Modifier.padding(8.dp), + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(all = 8.dp), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + text = "down", + modifier = Modifier.clickable { + progress = 0f + }, + ) + + Text( + text = "up", + modifier = Modifier.clickable { + progress += 0.1f + }, + ) + } + } +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilSelectButton.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilSelectButton.kt new file mode 100644 index 00000000..85167f5a --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilSelectButton.kt @@ -0,0 +1,131 @@ +package com.threegap.bitnagil.designsystem.component.atom + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +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.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.threegap.bitnagil.designsystem.BitnagilTheme + +@Composable +fun BitnagilSelectButton( + title: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, + description: String? = null, + selected: Boolean = false, + colors: BitnagilSelectButtonColor = BitnagilSelectButtonColor.default(), + shape: Shape = RoundedCornerShape(12.dp), +) { + val interactionSource = remember { MutableInteractionSource() } + val isPressed by interactionSource.collectIsPressedAsState() + + val backgroundColor = when { + isPressed -> colors.pressedBackgroundColor + selected -> colors.selectedBackgroundColor + else -> colors.defaultBackgroundColor + } + + val contentColor = when { + isPressed -> colors.pressedContentColor + selected -> colors.selectedContentColor + else -> colors.defaultContentColor + } + + Column( + modifier = modifier + .fillMaxWidth() + .clip(shape) + .background(backgroundColor) + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onClick, + ) + .padding(horizontal = 20.dp, vertical = 16.dp) + .semantics { + role = Role.Button + }, + verticalArrangement = Arrangement.Center, + ) { + Text( + text = title, + color = contentColor, + style = if (description == null) { + BitnagilTheme.typography.body1Regular + } else { + BitnagilTheme.typography.subtitle1SemiBold + }, + ) + + description?.let { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = description, + color = contentColor, + style = BitnagilTheme.typography.body2Regular, + ) + } + } +} + +@Immutable +data class BitnagilSelectButtonColor( + val defaultBackgroundColor: Color, + val selectedBackgroundColor: Color, + val pressedBackgroundColor: Color, + val defaultContentColor: Color, + val selectedContentColor: Color, + val pressedContentColor: Color, +) { + companion object { + @Composable + fun default(): BitnagilSelectButtonColor = BitnagilSelectButtonColor( + defaultBackgroundColor = BitnagilTheme.colors.white, + selectedBackgroundColor = BitnagilTheme.colors.lightBlue200, + pressedBackgroundColor = BitnagilTheme.colors.lightBlue200, + defaultContentColor = BitnagilTheme.colors.coolGray50, + selectedContentColor = BitnagilTheme.colors.navy500, + pressedContentColor = BitnagilTheme.colors.navy500, + ) + } +} + +@Preview +@Composable +private fun Preview() { + Column { + BitnagilSelectButton( + title = "루틴명", + onClick = {}, + ) + + Spacer(modifier = Modifier.height(12.dp)) + + BitnagilSelectButton( + title = "루틴명", + description = "세부 루틴 한 줄 설명", + onClick = {}, + ) + } +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilTextButton.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilTextButton.kt new file mode 100644 index 00000000..9b6340a2 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilTextButton.kt @@ -0,0 +1,144 @@ +package com.threegap.bitnagil.designsystem.component.atom + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.Box +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.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.threegap.bitnagil.designsystem.BitnagilTheme + +@Composable +fun BitnagilTextButton( + text: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + colors: BitnagilTextButtonColor = BitnagilTextButtonColor.default(), + shape: Shape = RoundedCornerShape(12.dp), + textStyle: TextStyle = BitnagilTheme.typography.body1SemiBold, + textDecoration: TextDecoration? = null, +) { + val interactionSource = remember { MutableInteractionSource() } + val isPressed by interactionSource.collectIsPressedAsState() + + val backgroundColor = when { + !enabled -> colors.disabledBackgroundColor + isPressed -> colors.pressedBackgroundColor + else -> colors.defaultBackgroundColor + } + + val textColor = when { + !enabled -> colors.disabledTextColor + isPressed -> colors.pressedTextColor + else -> colors.defaultTextColor + } + + Box( + modifier = modifier + .fillMaxWidth() + .height(54.dp) + .clip(shape) + .background(backgroundColor) + .clickable( + enabled = enabled, + onClick = onClick, + interactionSource = interactionSource, + indication = null, + ) + .semantics { + role = Role.Button + }, + contentAlignment = Alignment.Center, + ) { + Text( + text = text, + color = textColor, + style = textStyle, + textDecoration = textDecoration, + ) + } +} + +@Immutable +data class BitnagilTextButtonColor( + val defaultBackgroundColor: Color, + val pressedBackgroundColor: Color, + val disabledBackgroundColor: Color, + val defaultTextColor: Color, + val pressedTextColor: Color, + val disabledTextColor: Color, +) { + companion object { + @Composable + fun default(): BitnagilTextButtonColor = BitnagilTextButtonColor( + defaultBackgroundColor = BitnagilTheme.colors.navy500, + pressedBackgroundColor = BitnagilTheme.colors.navy700, + disabledBackgroundColor = BitnagilTheme.colors.navy50, + defaultTextColor = BitnagilTheme.colors.white, + pressedTextColor = BitnagilTheme.colors.coolGray70, + disabledTextColor = BitnagilTheme.colors.coolGray70, + ) + + @Composable + fun skip(): BitnagilTextButtonColor = BitnagilTextButtonColor( + defaultBackgroundColor = BitnagilTheme.colors.white, + pressedBackgroundColor = BitnagilTheme.colors.white, + disabledBackgroundColor = BitnagilTheme.colors.white, + defaultTextColor = BitnagilTheme.colors.navy500, + pressedTextColor = BitnagilTheme.colors.navy500, + disabledTextColor = BitnagilTheme.colors.navy500, + ) + } +} + +@Preview +@Composable +private fun BitnagilTextButtonPreview() { + Column(Modifier.padding(16.dp)) { + BitnagilTextButton( + text = "시작하기", + onClick = {}, + enabled = false, + ) + + Spacer(modifier = Modifier.height(12.dp)) + + BitnagilTextButton( + text = "시작하기", + onClick = {}, + ) + + Spacer(modifier = Modifier.height(12.dp)) + + BitnagilTextButton( + text = "건너뛰기", + onClick = {}, + colors = BitnagilTextButtonColor.skip(), + textStyle = BitnagilTheme.typography.body2Regular, + textDecoration = TextDecoration.Underline, + ) + } +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilOptionButton.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilOptionButton.kt new file mode 100644 index 00000000..5c8aed22 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilOptionButton.kt @@ -0,0 +1,54 @@ +package com.threegap.bitnagil.designsystem.component.block + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +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 BitnagilOptionButton( + title: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .height(48.dp) + .clickableWithoutRipple(onClick = onClick) + .padding(start = 16.dp, end = 2.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + text = title, + color = BitnagilTheme.colors.black, + style = BitnagilTheme.typography.body1Regular, + modifier = Modifier.weight(1f), + ) + + BitnagilIcon( + id = R.drawable.ic_right_arrow_20, + tint = BitnagilTheme.colors.black, + modifier = Modifier.padding(10.dp), + ) + } +} + +@Preview +@Composable +private fun BitnagilOptionButtonPreview() { + BitnagilOptionButton( + title = "공지사항", + onClick = {}, + ) +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilProgressTopBar.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilProgressTopBar.kt new file mode 100644 index 00000000..6e6cadf8 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilProgressTopBar.kt @@ -0,0 +1,51 @@ +package com.threegap.bitnagil.designsystem.component.block + +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.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.R +import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon +import com.threegap.bitnagil.designsystem.component.atom.BitnagilProgressBar +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple + +@Composable +fun BitnagilProgressTopBar( + progress: Float, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .height(54.dp) + .padding(start = 4.dp, end = 18.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ) { + BitnagilIcon( + id = R.drawable.ic_back_arrow_36, + modifier = Modifier.clickableWithoutRipple(onClick = onBackClick), + ) + + BitnagilProgressBar( + progress = progress, + modifier = Modifier, + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun BitnagilProgressTopBarPreview() { + BitnagilProgressTopBar( + progress = 0.5f, + onBackClick = {}, + ) +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilTopBar.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilTopBar.kt new file mode 100644 index 00000000..60bb7f7a --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilTopBar.kt @@ -0,0 +1,94 @@ +package com.threegap.bitnagil.designsystem.component.block + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.HorizontalDivider +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 BitnagilTopBar( + modifier: Modifier = Modifier, + title: String? = null, + showBackButton: Boolean = false, + onBackClick: () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, +) { + Box( + modifier = modifier + .fillMaxWidth() + .height(54.dp), + ) { + if (showBackButton) { + Box( + modifier = Modifier + .align(Alignment.CenterStart) + .padding(start = 4.dp) + .clickableWithoutRipple { onBackClick() }, + ) { + BitnagilIcon( + id = R.drawable.ic_back_arrow_36, + ) + } + } + + if (title != null) { + Text( + text = title, + color = BitnagilTheme.colors.coolGray10, + style = BitnagilTheme.typography.title3SemiBold, + modifier = Modifier.align(Alignment.Center), + ) + } + + Row( + modifier = Modifier + .align(Alignment.CenterEnd) + .padding(end = 10.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + actions() + } + } +} + +@Preview(showBackground = true) +@Composable +private fun Preview() { + Column { + BitnagilTopBar(title = "추천루틴") + + HorizontalDivider() + + BitnagilTopBar( + title = "설정", + showBackButton = true, + onBackClick = {}, + ) + + HorizontalDivider() + + BitnagilTopBar( + title = "마이페이지", + actions = { + BitnagilIcon( + id = R.drawable.ic_setting, + modifier = Modifier.padding(6.dp), + ) + }, + ) + } +} diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/modifier/ModifierExt.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/modifier/ModifierExt.kt new file mode 100644 index 00000000..1800b4b8 --- /dev/null +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/modifier/ModifierExt.kt @@ -0,0 +1,24 @@ +package com.threegap.bitnagil.designsystem.modifier + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.semantics.Role + +fun Modifier.clickableWithoutRipple( + enabled: Boolean = true, + onClickLabel: String? = null, + role: Role? = null, + onClick: () -> Unit, +) = composed { + clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + enabled = enabled, + onClickLabel = onClickLabel, + role = role, + onClick = onClick, + ) +} diff --git a/core/designsystem/src/main/res/drawable-hdpi/anxiety.png b/core/designsystem/src/main/res/drawable-hdpi/anxiety.png new file mode 100644 index 00000000..0a95dfc7 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/anxiety.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/calm.png b/core/designsystem/src/main/res/drawable-hdpi/calm.png new file mode 100644 index 00000000..8d1353bb Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/calm.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/default_ball.png b/core/designsystem/src/main/res/drawable-hdpi/default_ball.png new file mode 100644 index 00000000..e0110aa2 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/default_ball.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/fatigue.png b/core/designsystem/src/main/res/drawable-hdpi/fatigue.png new file mode 100644 index 00000000..9323b2e5 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/fatigue.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/intro_character.png b/core/designsystem/src/main/res/drawable-hdpi/intro_character.png new file mode 100644 index 00000000..8ac322e1 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/intro_character.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/lethargy.png b/core/designsystem/src/main/res/drawable-hdpi/lethargy.png new file mode 100644 index 00000000..8b2f0878 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/lethargy.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/onboarding_character.png b/core/designsystem/src/main/res/drawable-hdpi/onboarding_character.png new file mode 100644 index 00000000..23bcc02a Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/onboarding_character.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/satisfaction.png b/core/designsystem/src/main/res/drawable-hdpi/satisfaction.png new file mode 100644 index 00000000..1c0ae88a Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/satisfaction.png differ diff --git a/core/designsystem/src/main/res/drawable-hdpi/vitality.png b/core/designsystem/src/main/res/drawable-hdpi/vitality.png new file mode 100644 index 00000000..80696670 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-hdpi/vitality.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/anxiety.png b/core/designsystem/src/main/res/drawable-mdpi/anxiety.png new file mode 100644 index 00000000..e2c00d18 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/anxiety.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/calm.png b/core/designsystem/src/main/res/drawable-mdpi/calm.png new file mode 100644 index 00000000..d772cade Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/calm.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/default_ball.png b/core/designsystem/src/main/res/drawable-mdpi/default_ball.png new file mode 100644 index 00000000..35e59f94 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/default_ball.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/fatigue.png b/core/designsystem/src/main/res/drawable-mdpi/fatigue.png new file mode 100644 index 00000000..173f9c55 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/fatigue.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/intro_character.png b/core/designsystem/src/main/res/drawable-mdpi/intro_character.png new file mode 100644 index 00000000..0b139eed Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/intro_character.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/lethargy.png b/core/designsystem/src/main/res/drawable-mdpi/lethargy.png new file mode 100644 index 00000000..2abd4c7b Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/lethargy.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/onboarding_character.png b/core/designsystem/src/main/res/drawable-mdpi/onboarding_character.png new file mode 100644 index 00000000..9856dede Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/onboarding_character.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/satisfaction.png b/core/designsystem/src/main/res/drawable-mdpi/satisfaction.png new file mode 100644 index 00000000..506ccdee Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/satisfaction.png differ diff --git a/core/designsystem/src/main/res/drawable-mdpi/vitality.png b/core/designsystem/src/main/res/drawable-mdpi/vitality.png new file mode 100644 index 00000000..12f20aa0 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-mdpi/vitality.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/anxiety.png b/core/designsystem/src/main/res/drawable-xhdpi/anxiety.png new file mode 100644 index 00000000..bb127f2e Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/anxiety.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/calm.png b/core/designsystem/src/main/res/drawable-xhdpi/calm.png new file mode 100644 index 00000000..f0cb9df6 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/calm.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/default_ball.png b/core/designsystem/src/main/res/drawable-xhdpi/default_ball.png new file mode 100644 index 00000000..9b1470fd Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/default_ball.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/fatigue.png b/core/designsystem/src/main/res/drawable-xhdpi/fatigue.png new file mode 100644 index 00000000..125f79f9 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/fatigue.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/intro_character.png b/core/designsystem/src/main/res/drawable-xhdpi/intro_character.png new file mode 100644 index 00000000..6330d244 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/intro_character.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/lethargy.png b/core/designsystem/src/main/res/drawable-xhdpi/lethargy.png new file mode 100644 index 00000000..31e1ba6c Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/lethargy.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/onboarding_character.png b/core/designsystem/src/main/res/drawable-xhdpi/onboarding_character.png new file mode 100644 index 00000000..7c8b2a3f Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/onboarding_character.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/satisfaction.png b/core/designsystem/src/main/res/drawable-xhdpi/satisfaction.png new file mode 100644 index 00000000..29faa11f Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/satisfaction.png differ diff --git a/core/designsystem/src/main/res/drawable-xhdpi/vitality.png b/core/designsystem/src/main/res/drawable-xhdpi/vitality.png new file mode 100644 index 00000000..96d9f203 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xhdpi/vitality.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/anxiety.png b/core/designsystem/src/main/res/drawable-xxhdpi/anxiety.png new file mode 100644 index 00000000..3e72f38f Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/anxiety.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/calm.png b/core/designsystem/src/main/res/drawable-xxhdpi/calm.png new file mode 100644 index 00000000..406d4823 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/calm.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/default_ball.png b/core/designsystem/src/main/res/drawable-xxhdpi/default_ball.png new file mode 100644 index 00000000..8602a5bd Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/default_ball.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/fatigue.png b/core/designsystem/src/main/res/drawable-xxhdpi/fatigue.png new file mode 100644 index 00000000..e2d90ba4 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/fatigue.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/intro_character.png b/core/designsystem/src/main/res/drawable-xxhdpi/intro_character.png new file mode 100644 index 00000000..466a48c0 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/intro_character.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/lethargy.png b/core/designsystem/src/main/res/drawable-xxhdpi/lethargy.png new file mode 100644 index 00000000..b8a1725a Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/lethargy.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/onboarding_character.png b/core/designsystem/src/main/res/drawable-xxhdpi/onboarding_character.png new file mode 100644 index 00000000..61b2b4b2 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/onboarding_character.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/satisfaction.png b/core/designsystem/src/main/res/drawable-xxhdpi/satisfaction.png new file mode 100644 index 00000000..a636fd62 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/satisfaction.png differ diff --git a/core/designsystem/src/main/res/drawable-xxhdpi/vitality.png b/core/designsystem/src/main/res/drawable-xxhdpi/vitality.png new file mode 100644 index 00000000..332e286d Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxhdpi/vitality.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/anxiety.png b/core/designsystem/src/main/res/drawable-xxxhdpi/anxiety.png new file mode 100644 index 00000000..9b126777 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/anxiety.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/calm.png b/core/designsystem/src/main/res/drawable-xxxhdpi/calm.png new file mode 100644 index 00000000..76d410cb Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/calm.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/default_ball.png b/core/designsystem/src/main/res/drawable-xxxhdpi/default_ball.png new file mode 100644 index 00000000..06dc5a65 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/default_ball.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/fatigue.png b/core/designsystem/src/main/res/drawable-xxxhdpi/fatigue.png new file mode 100644 index 00000000..e44facca Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/fatigue.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/intro_character.png b/core/designsystem/src/main/res/drawable-xxxhdpi/intro_character.png new file mode 100644 index 00000000..87ef3c41 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/intro_character.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/lethargy.png b/core/designsystem/src/main/res/drawable-xxxhdpi/lethargy.png new file mode 100644 index 00000000..cf78d504 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/lethargy.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/onboarding_character.png b/core/designsystem/src/main/res/drawable-xxxhdpi/onboarding_character.png new file mode 100644 index 00000000..a4b5c486 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/onboarding_character.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/satisfaction.png b/core/designsystem/src/main/res/drawable-xxxhdpi/satisfaction.png new file mode 100644 index 00000000..f818fa89 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/satisfaction.png differ diff --git a/core/designsystem/src/main/res/drawable-xxxhdpi/vitality.png b/core/designsystem/src/main/res/drawable-xxxhdpi/vitality.png new file mode 100644 index 00000000..f6b5e4b2 Binary files /dev/null and b/core/designsystem/src/main/res/drawable-xxxhdpi/vitality.png differ diff --git a/core/designsystem/src/main/res/drawable/ic_add_routine.xml b/core/designsystem/src/main/res/drawable/ic_add_routine.xml new file mode 100644 index 00000000..1d026181 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_add_routine.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_arrow_down_up.xml b/core/designsystem/src/main/res/drawable/ic_arrow_down_up.xml new file mode 100644 index 00000000..ee960d07 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_arrow_down_up.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_back_arrow_20.xml b/core/designsystem/src/main/res/drawable/ic_back_arrow_20.xml new file mode 100644 index 00000000..3e030c61 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_back_arrow_20.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_back_arrow_36.xml b/core/designsystem/src/main/res/drawable/ic_back_arrow_36.xml new file mode 100644 index 00000000..2a5c1d5e --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_back_arrow_36.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_check.xml b/core/designsystem/src/main/res/drawable/ic_check.xml new file mode 100644 index 00000000..5d0294ed --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_check.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_close.xml b/core/designsystem/src/main/res/drawable/ic_close.xml new file mode 100644 index 00000000..1daad874 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_close.xml @@ -0,0 +1,18 @@ + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_detail_routine.xml b/core/designsystem/src/main/res/drawable/ic_detail_routine.xml new file mode 100644 index 00000000..b18b98ec --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_detail_routine.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_down_arrow.xml b/core/designsystem/src/main/res/drawable/ic_down_arrow.xml new file mode 100644 index 00000000..803466b2 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_down_arrow.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_edit.xml b/core/designsystem/src/main/res/drawable/ic_edit.xml new file mode 100644 index 00000000..eefe8caf --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_edit.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_kakao_login.xml b/core/designsystem/src/main/res/drawable/ic_kakao_login.xml new file mode 100644 index 00000000..3aa72c6b --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_kakao_login.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_name_routine.xml b/core/designsystem/src/main/res/drawable/ic_name_routine.xml new file mode 100644 index 00000000..dde84f8d --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_name_routine.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_plus.xml b/core/designsystem/src/main/res/drawable/ic_plus.xml new file mode 100644 index 00000000..e04e396a --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,18 @@ + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_report.xml b/core/designsystem/src/main/res/drawable/ic_report.xml new file mode 100644 index 00000000..aa86b3dc --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_report.xml @@ -0,0 +1,56 @@ + + + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_right_arrow_20.xml b/core/designsystem/src/main/res/drawable/ic_right_arrow_20.xml new file mode 100644 index 00000000..1585701e --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_right_arrow_20.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_rotate.xml b/core/designsystem/src/main/res/drawable/ic_rotate.xml new file mode 100644 index 00000000..e4a9c861 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_rotate.xml @@ -0,0 +1,13 @@ + + + diff --git a/core/designsystem/src/main/res/drawable/ic_see_more.xml b/core/designsystem/src/main/res/drawable/ic_see_more.xml new file mode 100644 index 00000000..d7c37b44 --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_see_more.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_setting.xml b/core/designsystem/src/main/res/drawable/ic_setting.xml new file mode 100644 index 00000000..4eaef82b --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_setting.xml @@ -0,0 +1,20 @@ + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_tooltip.xml b/core/designsystem/src/main/res/drawable/ic_tooltip.xml new file mode 100644 index 00000000..f2579aff --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_tooltip.xml @@ -0,0 +1,14 @@ + + + + diff --git a/core/designsystem/src/main/res/drawable/ic_trash.xml b/core/designsystem/src/main/res/drawable/ic_trash.xml new file mode 100644 index 00000000..096bb18f --- /dev/null +++ b/core/designsystem/src/main/res/drawable/ic_trash.xml @@ -0,0 +1,21 @@ + + + + diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt index 2e3fdfcb..fe071e53 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt @@ -2,17 +2,12 @@ package com.threegap.bitnagil.presentation.emotion import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -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.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items @@ -28,6 +23,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.common.flow.collectAsEffect import com.threegap.bitnagil.presentation.emotion.model.Emotion import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionSideEffect @@ -65,24 +62,18 @@ private fun EmotionScreen( .background(color = BitnagilTheme.colors.white), horizontalAlignment = Alignment.CenterHorizontally, ) { - Box( - modifier = Modifier - .height(54.dp) - .fillMaxWidth(), - ) { - Box( - modifier = Modifier - .padding(start = 2.dp) - .size(48.dp) - .background(BitnagilTheme.colors.black) - .align(Alignment.CenterStart) - .clickable(onClick = onClickPreviousButton), - ) - } + BitnagilTopBar( + showBackButton = true, + onBackClick = onClickPreviousButton, + ) Spacer(modifier = Modifier.height(32.dp)) - Text("오늘의 감정구슬을 골라보세요", style = BitnagilTheme.typography.title2Bold.copy(color = BitnagilTheme.colors.navy500), textAlign = TextAlign.Center) + Text( + "오늘의 감정구슬을 골라보세요", + style = BitnagilTheme.typography.title2Bold.copy(color = BitnagilTheme.colors.navy500), + textAlign = TextAlign.Center, + ) Spacer(modifier = Modifier.height(6.dp)) @@ -96,23 +87,24 @@ private fun EmotionScreen( LazyVerticalGrid( columns = GridCells.Fixed(3), - modifier = Modifier.padding(horizontal = 40.dp).widthIn(300.dp), - horizontalArrangement = Arrangement.spacedBy(32.dp), - verticalArrangement = Arrangement.spacedBy(32.dp), + modifier = Modifier.padding(horizontal = 24.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalArrangement = Arrangement.spacedBy(28.dp), ) { items(state.emotions) { emotion -> Column( + modifier = Modifier + .clickableWithoutRipple { onClickEmotion(emotion) }, horizontalAlignment = Alignment.CenterHorizontally, ) { Image( painter = painterResource(id = emotion.imageResourceId), contentDescription = null, - modifier = Modifier.size(72.dp).clickable { - onClickEmotion(emotion) - }, ) - Spacer(modifier = Modifier.height(12.dp)) - Text(emotion.emotionName, style = BitnagilTheme.typography.body1Regular.copy(color = BitnagilTheme.colors.coolGray20)) + Text( + text = emotion.emotionName, + style = BitnagilTheme.typography.body1Regular.copy(color = BitnagilTheme.colors.coolGray20), + ) } } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt index d1afc1de..415935a5 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/model/Emotion.kt @@ -1,18 +1,18 @@ package com.threegap.bitnagil.presentation.emotion.model +import com.threegap.bitnagil.designsystem.R import com.threegap.bitnagil.domain.emotion.model.Emotion as DomainEmotion enum class Emotion( val emotionName: String, val imageResourceId: Int, ) { - // todo - 이미지 리소스 전달받은 후 해당 이미지로 수정 - CALM(emotionName = "평온함", imageResourceId = android.R.drawable.ic_menu_report_image), - VITALITY(emotionName = "활기참", imageResourceId = android.R.drawable.ic_menu_report_image), - LETHARGY(emotionName = "무기력함", imageResourceId = android.R.drawable.ic_menu_report_image), - ANXIETY(emotionName = "불안함", imageResourceId = android.R.drawable.ic_menu_report_image), - SATISFACTION(emotionName = "만족함", imageResourceId = android.R.drawable.ic_menu_report_image), - FATIGUE(emotionName = "피로함", imageResourceId = android.R.drawable.ic_menu_report_image), + CALM(emotionName = "평온함", imageResourceId = R.drawable.calm), + VITALITY(emotionName = "활기참", imageResourceId = R.drawable.vitality), + LETHARGY(emotionName = "무기력함", imageResourceId = R.drawable.lethargy), + ANXIETY(emotionName = "불안함", imageResourceId = R.drawable.anxiety), + SATISFACTION(emotionName = "만족함", imageResourceId = R.drawable.satisfaction), + FATIGUE(emotionName = "피로함", imageResourceId = R.drawable.fatigue), ; companion object { diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt index 79bf539f..a6630a0a 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt @@ -1,7 +1,6 @@ package com.threegap.bitnagil.presentation.home import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -9,19 +8,14 @@ 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.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Menu -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -29,6 +23,9 @@ import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle 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 import com.threegap.bitnagil.presentation.home.component.template.CollapsibleHomeHeader import com.threegap.bitnagil.presentation.home.component.template.DeleteConfirmDialog import com.threegap.bitnagil.presentation.home.component.template.RoutineDetailsBottomSheet @@ -146,8 +143,8 @@ private fun HomeScreen( .background( brush = Brush.linearGradient( colors = listOf( - Color(0xFFFFEADF), - BitnagilTheme.colors.lightBlue75, + BitnagilTheme.colors.homeGradientStartColor, + BitnagilTheme.colors.homeGradientEndColor, ), start = Offset(0f, 0f), end = Offset(collapsibleHeaderState.screenHeight.value, collapsibleHeaderState.screenWidth.value * 2), @@ -221,16 +218,13 @@ private fun HomeScreen( ) if (index == 0) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.Menu, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_arrow_down_up, + tint = BitnagilTheme.colors.navy200, modifier = Modifier .align(Alignment.TopEnd) .padding(end = 4.dp) - .clickable { onShowRoutineSortBottomSheet() } - .padding(8.dp) - .size(24.dp) + .clickableWithoutRipple { onShowRoutineSortBottomSheet() } .zIndex(1f), ) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/atom/EmotionBall.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/atom/EmotionBall.kt new file mode 100644 index 00000000..0e71603f --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/atom/EmotionBall.kt @@ -0,0 +1,151 @@ +package com.threegap.bitnagil.presentation.home.component.atom + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.threegap.bitnagil.designsystem.R +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple +import com.threegap.bitnagil.presentation.home.model.EmotionBallType + +@Composable +fun EmotionBall( + emotionType: EmotionBallType?, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + if (emotionType != null) { + Image( + painter = painterResource(emotionType.drawableId), + contentDescription = null, + modifier = modifier + .size(172.dp) + .clickableWithoutRipple { onClick() } + .padding(10.dp) + .fillMaxSize() + .shadow( + elevation = 24.dp, + shape = CircleShape, + ambientColor = emotionType.ambientColor, + spotColor = emotionType.spotColor, + ), + ) + } else { + Image( + painter = painterResource(R.drawable.default_ball), + contentDescription = null, + modifier = modifier + .size(172.dp) + .clickableWithoutRipple { onClick() } + .fillMaxSize(), + ) + } +} + +@Preview(showBackground = true, name = "Default (Null)") +@Composable +private fun EmotionBallDefaultPreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = null, + onClick = {}, + ) + } +} + +@Preview(showBackground = true, name = "Calm") +@Composable +private fun EmotionBallCalmPreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = EmotionBallType.CALM, + onClick = {}, + ) + } +} + +@Preview(showBackground = true, name = "Vitality") +@Composable +private fun EmotionBallVitalityPreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = EmotionBallType.VITALITY, + onClick = {}, + ) + } +} + +@Preview(showBackground = true, name = "Lethargy") +@Composable +private fun EmotionBallLethargyPreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = EmotionBallType.LETHARGY, + onClick = {}, + ) + } +} + +@Preview(showBackground = true, name = "Anxiety") +@Composable +private fun EmotionBallAnxietyPreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = EmotionBallType.ANXIETY, + onClick = {}, + ) + } +} + +@Preview(showBackground = true, name = "Satisfaction") +@Composable +private fun EmotionBallSatisfactionPreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = EmotionBallType.SATISFACTION, + onClick = {}, + ) + } +} + +@Preview(showBackground = true, name = "Fatigue") +@Composable +private fun EmotionBallFatiguePreview() { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + EmotionBall( + emotionType = EmotionBallType.FATIGUE, + onClick = {}, + ) + } +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt index b4b06a98..d1b90329 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/RoutineItem.kt @@ -1,26 +1,23 @@ package com.threegap.bitnagil.presentation.home.component.block import androidx.compose.foundation.background -import androidx.compose.foundation.clickable 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.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material3.Icon import androidx.compose.material3.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.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.BitnagilCheckBox +import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.domain.routine.model.RoutineType import com.threegap.bitnagil.presentation.home.model.RoutineUiModel import com.threegap.bitnagil.presentation.home.model.SubRoutineUiModel @@ -37,8 +34,7 @@ fun RoutineItem( verticalAlignment = Alignment.CenterVertically, modifier = modifier .fillMaxWidth() - // todo: 리플효과 제거하기 - .clickable( + .clickableWithoutRipple( onClick = { onRoutineToggle(!routine.isCompleted) }, ) .height(61.dp) @@ -54,11 +50,8 @@ fun RoutineItem( horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically, ) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, - tint = if (routine.isCompleted) Color.Black else Color.Gray, + BitnagilCheckBox( + checked = routine.isCompleted, ) Text( @@ -68,17 +61,9 @@ fun RoutineItem( ) } - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.MoreVert, - contentDescription = null, - modifier = Modifier - // todo: 리플효과 제거하기 - .clickable { - onMoreClick() - } - .padding(12.dp) - .size(24.dp), + BitnagilIcon( + id = R.drawable.ic_see_more, + modifier = Modifier.clickableWithoutRipple(onClick = onMoreClick), ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt index 528616f8..64e96c3e 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/block/SubRoutinesItem.kt @@ -1,6 +1,5 @@ package com.threegap.bitnagil.presentation.home.component.block -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -8,9 +7,7 @@ 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.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.Icon +import androidx.compose.foundation.layout.size import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -18,6 +15,9 @@ 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 import com.threegap.bitnagil.domain.routine.model.RoutineType import com.threegap.bitnagil.presentation.home.model.SubRoutineUiModel @@ -44,11 +44,11 @@ fun SubRoutinesItem( subRoutines.forEach { subRoutine -> Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(11.dp), + horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier .fillMaxWidth() - // todo: 리플효과 제거하기 - .clickable { + .height(34.dp) + .clickableWithoutRipple { onSubRoutineToggle(subRoutine.subRoutineId, !subRoutine.isCompleted) } .padding( @@ -56,15 +56,14 @@ fun SubRoutinesItem( horizontal = 14.dp, ), ) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_check, tint = if (subRoutine.isCompleted) { BitnagilTheme.colors.orange500 } else { BitnagilTheme.colors.coolGray96 }, + modifier = Modifier.size(20.dp), ) Text( diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt index 918bbb31..207ec100 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/CollapsibleHomeHeader.kt @@ -1,6 +1,5 @@ package com.threegap.bitnagil.presentation.home.component.template -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -9,12 +8,6 @@ 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.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight -import androidx.compose.material.icons.filled.AccountBox -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -29,6 +22,9 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple +import com.threegap.bitnagil.presentation.home.component.atom.EmotionBall import com.threegap.bitnagil.presentation.home.component.block.SpeechBubbleTooltip import com.threegap.bitnagil.presentation.home.util.CollapsibleHeaderState import com.threegap.bitnagil.presentation.home.util.rememberCollapsibleHeaderState @@ -78,7 +74,7 @@ fun CollapsibleHomeHeader( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(2.dp), modifier = Modifier - .clickable { onEmotionRecordClick() } + .clickableWithoutRipple { onEmotionRecordClick() } .padding(vertical = 11.dp), ) { Text( @@ -86,20 +82,24 @@ fun CollapsibleHomeHeader( style = BitnagilTheme.typography.caption1Medium, color = BitnagilTheme.colors.navy300, ) - Icon( - imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, - contentDescription = null, - modifier = Modifier.size(20.dp), + + BitnagilIcon( + id = com.threegap.bitnagil.designsystem.R.drawable.ic_right_arrow_20, tint = BitnagilTheme.colors.navy300, ) } } - EmotionBallIcon( - modifier = Modifier - .padding(end = 18.dp, bottom = 42.dp) + Box( + modifier = modifier + .padding(10.dp) .align(Alignment.BottomEnd), - ) + ) { + EmotionBall( + emotionType = null, + onClick = {}, + ) + } } } } @@ -123,13 +123,10 @@ private fun GreetingMessage( ) Box { - Icon( - imageVector = Icons.Outlined.Info, - contentDescription = null, - modifier = Modifier - .clickable { onInfoClick() } - .padding(4.dp) - .size(16.dp), + BitnagilIcon( + id = com.threegap.bitnagil.designsystem.R.drawable.ic_tooltip, + tint = null, + modifier = Modifier.clickableWithoutRipple { onInfoClick() }, ) if (showTooltip) { @@ -147,18 +144,6 @@ private fun GreetingMessage( } } -@Composable -private fun EmotionBallIcon( - modifier: Modifier = Modifier, -) { - // TODO: 감정구슬 그래픽으로 수정하기 - Icon( - imageVector = Icons.Default.AccountBox, - contentDescription = "감정구슬", - modifier = modifier.size(102.dp), - ) -} - @Preview @Composable private fun HomeTopBarPreview() { diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/DeleteConfirmDialog.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/DeleteConfirmDialog.kt index 4e38cf74..b7202981 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/DeleteConfirmDialog.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/DeleteConfirmDialog.kt @@ -2,7 +2,6 @@ package com.threegap.bitnagil.presentation.home.component.template import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -22,6 +21,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -65,9 +65,14 @@ fun DeleteConfirmDialog( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() - .clickable { onDeleteToday() } + .clickableWithoutRipple { onDeleteToday() } .height(44.dp) .background( + color = BitnagilTheme.colors.white, + shape = RoundedCornerShape(8.dp), + ) + .border( + width = 1.dp, color = BitnagilTheme.colors.navy500, shape = RoundedCornerShape(8.dp), ), @@ -75,7 +80,7 @@ fun DeleteConfirmDialog( Text( text = "선택한 요일만 삭제", style = BitnagilTheme.typography.body2Medium, - color = BitnagilTheme.colors.white, + color = BitnagilTheme.colors.navy500, modifier = Modifier.padding(vertical = 8.dp), ) } @@ -84,7 +89,7 @@ fun DeleteConfirmDialog( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() - .clickable { onDeleteAll() } + .clickableWithoutRipple { onDeleteAll() } .height(44.dp) .background( color = BitnagilTheme.colors.white, @@ -99,7 +104,7 @@ fun DeleteConfirmDialog( Text( text = "전체 루틴 삭제", style = BitnagilTheme.typography.body2Medium, - color = BitnagilTheme.colors.black, + color = BitnagilTheme.colors.navy500, modifier = Modifier.padding(vertical = 8.dp), ) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt index 586ce577..b79a7bb0 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineDetailsBottomSheet.kt @@ -2,7 +2,6 @@ package com.threegap.bitnagil.presentation.home.component.template import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -23,6 +22,9 @@ import androidx.compose.ui.text.style.TextAlign 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 import com.threegap.bitnagil.domain.routine.model.DayOfWeek import com.threegap.bitnagil.domain.routine.model.DayOfWeek.Companion.formatRepeatDays import com.threegap.bitnagil.domain.routine.model.RoutineType @@ -70,13 +72,25 @@ private fun RoutineInfoContent( Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .height(28.dp), ) { - Text( - text = "루틴 이름", - color = BitnagilTheme.colors.coolGray50, - style = BitnagilTheme.typography.body2Medium, - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ) { + BitnagilIcon( + id = R.drawable.ic_name_routine, + tint = BitnagilTheme.colors.coolGray50, + ) + + Text( + text = "루틴 이름", + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.body2Medium, + ) + } Text( text = routine.routineName, color = BitnagilTheme.colors.coolGray10, @@ -87,19 +101,29 @@ private fun RoutineInfoContent( Box( modifier = Modifier.fillMaxWidth(), ) { - Text( - text = "세부 루틴", - color = BitnagilTheme.colors.coolGray50, - style = BitnagilTheme.typography.body2Medium, + Row( modifier = Modifier.align(Alignment.TopStart), - ) + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ) { + BitnagilIcon( + id = R.drawable.ic_detail_routine, + tint = BitnagilTheme.colors.coolGray50, + ) + + Text( + text = "세부 루틴", + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.body2Medium, + ) + } if (routine.subRoutines.isEmpty()) { Text( text = "세부루틴 없음", - color = BitnagilTheme.colors.navy500, - style = BitnagilTheme.typography.body2Medium, - modifier = Modifier.align(Alignment.TopEnd), + color = BitnagilTheme.colors.coolGray10, + style = BitnagilTheme.typography.body2SemiBold, + modifier = Modifier.align(Alignment.CenterEnd), ) } else { Column( @@ -111,7 +135,9 @@ private fun RoutineInfoContent( color = BitnagilTheme.colors.coolGray10, style = BitnagilTheme.typography.body2SemiBold, textAlign = TextAlign.End, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), ) } } @@ -122,13 +148,26 @@ private fun RoutineInfoContent( Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .height(28.dp), ) { - Text( - text = "루틴 반복", - color = BitnagilTheme.colors.coolGray50, - style = BitnagilTheme.typography.body2Medium, - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ) { + BitnagilIcon( + id = R.drawable.ic_rotate, + tint = BitnagilTheme.colors.coolGray50, + ) + + Text( + text = "루틴 반복", + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.body2Medium, + ) + } + Text( text = routine.repeatDay.formatRepeatDays(), color = BitnagilTheme.colors.coolGray10, @@ -163,13 +202,22 @@ private fun RoutineInfoContent( color = BitnagilTheme.colors.navy500, shape = RoundedCornerShape(12.dp), ) - .clickable { onEdit() }, + .clickableWithoutRipple { onEdit() }, ) { - Text( - text = "수정하기", - color = BitnagilTheme.colors.white, - style = BitnagilTheme.typography.body2Medium, - ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + BitnagilIcon( + id = com.threegap.bitnagil.designsystem.R.drawable.ic_edit, + tint = BitnagilTheme.colors.white, + ) + Text( + text = "수정하기", + color = BitnagilTheme.colors.white, + style = BitnagilTheme.typography.subtitle1SemiBold, + ) + } } Box( @@ -186,13 +234,22 @@ private fun RoutineInfoContent( color = BitnagilTheme.colors.white, shape = RoundedCornerShape(12.dp), ) - .clickable { onDelete() }, + .clickableWithoutRipple { onDelete() }, ) { - Text( - text = "삭제하기", - color = BitnagilTheme.colors.navy500, - style = BitnagilTheme.typography.body2Medium, - ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + BitnagilIcon( + id = com.threegap.bitnagil.designsystem.R.drawable.ic_trash, + tint = BitnagilTheme.colors.navy500, + ) + Text( + text = "삭제하기", + color = BitnagilTheme.colors.navy500, + style = BitnagilTheme.typography.subtitle1SemiBold, + ) + } } } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineEmptyView.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineEmptyView.kt index 34ea25bf..11a62c20 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineEmptyView.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineEmptyView.kt @@ -1,7 +1,6 @@ package com.threegap.bitnagil.presentation.home.component.template import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -16,6 +15,7 @@ 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.modifier.clickableWithoutRipple @Composable fun RoutineEmptyView( @@ -46,10 +46,7 @@ fun RoutineEmptyView( color = BitnagilTheme.colors.navy50, shape = RoundedCornerShape(100.dp), ) - // todo: 리플효과 제거하기 - .clickable { - onRegisterRoutineClick() - } + .clickableWithoutRipple { onRegisterRoutineClick() } .padding( vertical = 8.dp, horizontal = 10.dp, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSortBottomSheet.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSortBottomSheet.kt index 978b3a0a..63b754c7 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSortBottomSheet.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/RoutineSortBottomSheet.kt @@ -1,17 +1,13 @@ package com.threegap.bitnagil.presentation.home.component.template -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column 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.material.icons.Icons -import androidx.compose.material.icons.filled.Check import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState @@ -22,6 +18,9 @@ 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 import com.threegap.bitnagil.presentation.home.model.RoutineSortType import kotlinx.coroutines.launch @@ -107,10 +106,7 @@ private fun SortOptionItem( .fillMaxWidth() .padding(vertical = 8.dp) .height(36.dp) - .clickable { - onClick(sortType) - // 짧은 지연 후 바텀시트 닫기 (선택적) - }, + .clickableWithoutRipple { onClick(sortType) }, ) { Text( text = text, @@ -120,10 +116,8 @@ private fun SortOptionItem( ) if (isSelected) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_check, tint = BitnagilTheme.colors.orange500, ) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/WeeklyDatePicker.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/WeeklyDatePicker.kt index b94e03f2..9da34285 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/WeeklyDatePicker.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/component/template/WeeklyDatePicker.kt @@ -1,7 +1,6 @@ package com.threegap.bitnagil.presentation.home.component.template import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -10,10 +9,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft -import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -26,6 +21,9 @@ import androidx.compose.ui.graphics.Color 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 import com.threegap.bitnagil.presentation.home.util.formatDayOfMonth import com.threegap.bitnagil.presentation.home.util.formatDayOfWeekShort import com.threegap.bitnagil.presentation.home.util.formatMonthYear @@ -63,26 +61,29 @@ fun WeeklyDatePicker( Row( verticalAlignment = Alignment.CenterVertically, ) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.AutoMirrored.Filled.KeyboardArrowLeft, - contentDescription = null, + Box( modifier = Modifier - // todo: 리플효과 제거하기 - .clickable { onPreviousWeekClick() } - .padding(14.dp) - .size(20.dp), - ) - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, - contentDescription = null, + .clickableWithoutRipple(onClick = onPreviousWeekClick) + .padding(14.dp), + contentAlignment = Alignment.Center, + ) { + BitnagilIcon( + id = R.drawable.ic_back_arrow_20, + tint = BitnagilTheme.colors.black, + ) + } + + Box( modifier = Modifier - // todo: 리플효과 제거하기 - .clickable { onNextWeekClick() } - .padding(14.dp) - .size(20.dp), - ) + .clickableWithoutRipple(onClick = onNextWeekClick) + .padding(14.dp), + contentAlignment = Alignment.Center, + ) { + BitnagilIcon( + id = R.drawable.ic_right_arrow_20, + tint = BitnagilTheme.colors.black, + ) + } } } @@ -118,9 +119,7 @@ private fun DateItem( Column( verticalArrangement = Arrangement.spacedBy(7.dp), horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - // todo: 리플효과 제거하기 - .clickable { onDateClick() }, + modifier = Modifier.clickableWithoutRipple { onDateClick() }, ) { Text( text = if (!isToday) date.formatDayOfWeekShort() else "오늘", diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt new file mode 100644 index 00000000..0e319db9 --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/EmotionBallType.kt @@ -0,0 +1,42 @@ +package com.threegap.bitnagil.presentation.home.model + +import androidx.annotation.DrawableRes +import androidx.compose.ui.graphics.Color +import com.threegap.bitnagil.designsystem.R + +enum class EmotionBallType( + @DrawableRes val drawableId: Int, + val ambientColor: Color, + val spotColor: Color, +) { + CALM( + drawableId = R.drawable.calm, + ambientColor = Color(0xFFB987FF).copy(alpha = 0.57f), + spotColor = Color(0xFFB987FF), + ), + VITALITY( + R.drawable.vitality, + ambientColor = Color(0xFF55840F).copy(alpha = 0.25f), + spotColor = Color(0xFF55840F), + ), + LETHARGY( + R.drawable.lethargy, + ambientColor = Color(0xFF000000).copy(alpha = 0.19f), + spotColor = Color(0xFF000000), + ), + ANXIETY( + R.drawable.anxiety, + ambientColor = Color(0xFFDE4C17).copy(alpha = 0.33f), + spotColor = Color(0xFFDE4C17), + ), + SATISFACTION( + R.drawable.satisfaction, + ambientColor = Color(0xFF24846B).copy(alpha = 0.28f), + spotColor = Color(0xFF24846B), + ), + FATIGUE( + R.drawable.fatigue, + ambientColor = Color(0xFFC71A1A).copy(alpha = 0.28f), + spotColor = Color(0xFFC71A1A), + ), +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/intro/IntroScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/intro/IntroScreen.kt index 284b7dff..4af0556d 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/intro/IntroScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/intro/IntroScreen.kt @@ -1,23 +1,28 @@ package com.threegap.bitnagil.presentation.intro -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box +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.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button import androidx.compose.material3.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.layout.ContentScale +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalWindowInfo +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.R +import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButton import com.threegap.bitnagil.presentation.intro.model.IntroIntent import com.threegap.bitnagil.presentation.intro.model.IntroSideEffect import org.orbitmvi.orbit.compose.collectSideEffect @@ -45,47 +50,46 @@ private fun IntroScreen( onStartButtonClick: () -> Unit, modifier: Modifier = Modifier, ) { + val windowInfo = LocalWindowInfo.current + val screenHeight = with(LocalDensity.current) { + windowInfo.containerSize.height.toDp() + } + Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = modifier - .fillMaxSize() - .padding(horizontal = 16.dp), + modifier = modifier.fillMaxSize(), ) { + Spacer(modifier = Modifier.height(screenHeight * 0.0748f)) + Text( text = "당신의 하루 리듬을 이해하고,\n작은 변화를 함께 시작해볼게요.", + color = BitnagilTheme.colors.navy500, + style = BitnagilTheme.typography.title2Bold, textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - .padding(top = 48.dp), + modifier = Modifier.fillMaxWidth(), ) - Spacer( - modifier = Modifier.height(38.dp), - ) + Spacer(modifier = Modifier.height(screenHeight * 0.151f)) - Box( + Image( + painter = painterResource(R.drawable.intro_character), + contentDescription = null, + contentScale = ContentScale.Fit, modifier = Modifier - .background(Color.Gray) - .fillMaxWidth() - .height(458.dp), - ) { - Text( - text = "빛나길 로고", - ) - } - - Spacer( - modifier = Modifier.height(38.dp), + .padding(50.dp) + .aspectRatio(260f / 295f), ) - Button( + Spacer(modifier = Modifier.weight(1f)) + + BitnagilTextButton( + text = "시작하기", onClick = onStartButtonClick, modifier = Modifier .fillMaxWidth() + .padding(horizontal = 16.dp) .padding(bottom = 20.dp), - ) { - Text("시작하기") - } + ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt index bf81620a..bbe92722 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/MyPageScreen.kt @@ -2,13 +2,9 @@ package com.threegap.bitnagil.presentation.mypage import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -26,6 +22,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel 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.component.block.BitnagilOptionButton +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.mypage.model.MyPageState @Composable @@ -61,26 +62,17 @@ private fun MyPageScreen( .background(color = BitnagilTheme.colors.white), horizontalAlignment = Alignment.CenterHorizontally, ) { - Box( - modifier = Modifier - .height(54.dp) - .fillMaxWidth(), - ) { - Text( - "마이페이지", - modifier = Modifier.align(Alignment.Center), - style = BitnagilTheme.typography.title3SemiBold, - ) - - Box( - modifier = Modifier - .padding(end = 10.dp) - .size(36.dp) - .background(BitnagilTheme.colors.black) - .align(Alignment.CenterEnd) - .clickable(onClick = onClickSetting), - ) - } + BitnagilTopBar( + title = "마이페이지", + actions = { + BitnagilIcon( + id = R.drawable.ic_setting, + modifier = Modifier + .clickableWithoutRipple(onClick = onClickSetting) + .padding(6.dp), + ) + }, + ) Spacer(modifier = Modifier.height(32.dp)) @@ -93,7 +85,8 @@ private fun MyPageScreen( ) Text( - state.name, + text = state.name, + color = BitnagilTheme.colors.coolGray5, style = BitnagilTheme.typography.title3SemiBold, modifier = Modifier.padding(top = 12.dp), ) @@ -104,68 +97,20 @@ private fun MyPageScreen( Spacer(modifier = Modifier.height(16.dp)) - Row( - modifier = Modifier - .height(48.dp) - .clickable(onClick = onClickResetOnBoarding) - .padding(start = 16.dp, end = 4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - "내 목표 재설정", - style = BitnagilTheme.typography.body1Regular, - modifier = Modifier.weight(1f), - ) - - Box( - modifier = Modifier - .padding(end = 10.dp) - .size(36.dp) - .background(BitnagilTheme.colors.black), - ) - } - - Row( - modifier = Modifier - .height(48.dp) - .clickable(onClick = onClickNotice) - .padding(start = 16.dp, end = 4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - "공지사항", - style = BitnagilTheme.typography.body1Regular, - modifier = Modifier.weight(1f), - ) - - Box( - modifier = Modifier - .padding(end = 10.dp) - .size(36.dp) - .background(BitnagilTheme.colors.black), - ) - } + BitnagilOptionButton( + title = "내 목표 재설정", + onClick = onClickResetOnBoarding, + ) - Row( - modifier = Modifier - .height(48.dp) - .clickable(onClick = onClickQnA) - .padding(start = 16.dp, end = 4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - "자주 묻는 질문", - style = BitnagilTheme.typography.body1Regular, - modifier = Modifier.weight(1f), - ) + BitnagilOptionButton( + title = "공지사항", + onClick = onClickNotice, + ) - Box( - modifier = Modifier - .padding(end = 10.dp) - .size(36.dp) - .background(BitnagilTheme.colors.black), - ) - } + BitnagilOptionButton( + title = "자주 묻는 질문", + onClick = onClickQnA, + ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt index 444f5a62..69c623ef 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/OnBoardingScreen.kt @@ -1,23 +1,17 @@ package com.threegap.bitnagil.presentation.onboarding -import android.R import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.block.BitnagilProgressTopBar import com.threegap.bitnagil.presentation.common.flow.collectAsEffect -import com.threegap.bitnagil.presentation.onboarding.component.atom.iconbutton.IconButton -import com.threegap.bitnagil.presentation.onboarding.component.atom.progress.OnBoardingProgressBar import com.threegap.bitnagil.presentation.onboarding.component.template.OnBoardingAbstractTemplate import com.threegap.bitnagil.presentation.onboarding.component.template.OnBoardingSelectTemplate import com.threegap.bitnagil.presentation.onboarding.model.OnBoardingPageInfo @@ -69,22 +63,13 @@ private fun OnBoardingScreen( onClickSkip: () -> Unit, ) { Column( - modifier = Modifier.background(color = Color(0xFFF7F7F8)), + modifier = Modifier + .background(BitnagilTheme.colors.coolGray99), ) { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - IconButton( - modifier = Modifier.padding(start = 4.dp, top = 9.dp, bottom = 9.dp), - svgResourceId = R.drawable.ic_delete, - onClick = onClickPreviousInSelectOnBoarding, - ) - - OnBoardingProgressBar( - modifier = Modifier.padding(start = 12.dp, end = 18.5.dp), - progress = state.progress, - ) - } + BitnagilProgressTopBar( + onBackClick = onClickPreviousInSelectOnBoarding, + progress = state.progress, + ) when (state) { is OnBoardingState.Idle -> { diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/iconbutton/IconButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/iconbutton/IconButton.kt deleted file mode 100644 index f9ccfc8b..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/iconbutton/IconButton.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.atom.iconbutton - -import androidx.annotation.DrawableRes -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsPressedAsState -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp - -@Composable -fun IconButton( - modifier: Modifier = Modifier, - @DrawableRes svgResourceId: Int, - contentDescription: String? = null, - onClick: () -> Unit, - defaultColor: Color = Color.Black, - pressedColor: Color = Color.Gray, -) { - val interactionSource = remember { MutableInteractionSource() } - val isPressed by interactionSource.collectIsPressedAsState() - - val iconColor = if (isPressed) pressedColor else defaultColor - - Box( - modifier = modifier - .size(36.dp) // 전체 버튼 크기 - .clickable( - interactionSource = interactionSource, - indication = null, // 기본 Ripple 효과 제거 (필요시 null 대신 rememberRipple() 사용) - onClick = onClick, - ), - contentAlignment = Alignment.Center, // 내부 아이콘을 중앙에 배치 - ) { - Image( - painter = painterResource(svgResourceId), - contentDescription = contentDescription, - modifier = Modifier.size(24.dp), // 내부 아이콘 크기 - colorFilter = ColorFilter.tint(iconColor), // 아이콘 색상 적용 - ) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/iconbutton/Preview.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/iconbutton/Preview.kt deleted file mode 100644 index 4cdcb884..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/iconbutton/Preview.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.atom.iconbutton - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.Preview - -@Preview(showBackground = true, backgroundColor = 0xFFFFFFFF) -@Composable -fun IconButtonPreview() { - IconButton( - svgResourceId = android.R.drawable.ic_menu_search, - contentDescription = "Search Icon", - onClick = {}, - ) -} - -@Preview(showBackground = true, backgroundColor = 0xFFFFFFFF) -@Composable -fun IconButtonPressedPreview() { - IconButton( - svgResourceId = android.R.drawable.ic_menu_add, - contentDescription = "Add Icon", - onClick = {}, - ) -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/progress/OnBoardingProgress.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/progress/OnBoardingProgress.kt deleted file mode 100644 index 15a80709..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/progress/OnBoardingProgress.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.atom.progress - -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.tween -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -@Composable -fun OnBoardingProgressBar( - modifier: Modifier = Modifier, - progress: Float, - height: Dp = 8.dp, - gradientStartColor: Color = Color(0xFFADD8E6), - gradientEndColor: Color = Color(0xFFFFB6C1), - backgroundColor: Color = Color(0xFFE0E0E0), -) { - val animatedProgress by animateFloatAsState( - targetValue = progress.coerceIn(0f, 1f), - label = "ProgressBarAnimation", - animationSpec = tween(durationMillis = 100, easing = LinearEasing), - ) - - Canvas( - modifier = modifier - .fillMaxWidth() - .height(height), - ) { - val strokeWidth = size.height - - drawLine( - color = backgroundColor, - start = Offset(0f, size.height / 2), - end = Offset(size.width, size.height / 2), - strokeWidth = strokeWidth, - cap = StrokeCap.Round, - ) - - if (animatedProgress > 0) { - val progressEndX = size.width * animatedProgress - drawLine( - brush = Brush.horizontalGradient( - colors = listOf(gradientStartColor, gradientEndColor), - startX = 0f, - endX = progressEndX, - ), - start = Offset(0f, size.height / 2), - end = Offset(progressEndX, size.height / 2), - strokeWidth = strokeWidth, - cap = StrokeCap.Round, - ) - } - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/progress/Preview.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/progress/Preview.kt deleted file mode 100644 index 5ad548c2..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/progress/Preview.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.atom.progress - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp - -@Preview(showBackground = true, widthDp = 300) -@Composable -fun OnBoardingProgressBarPreview() { - var progress by remember { mutableFloatStateOf(0.0f) } - - Column { - OnBoardingProgressBar(progress = progress, modifier = Modifier.padding(8.dp)) - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(all = 8.dp), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - Text( - "down", - modifier = Modifier.clickable { - progress = 0f - }, - ) - - Text( - "up", - modifier = Modifier.clickable { - progress = progress + 0.1f - }, - ) - } - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/textbutton/Preview.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/textbutton/Preview.kt deleted file mode 100644 index d22833a1..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/textbutton/Preview.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.atom.textbutton - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp - -@Preview(showBackground = true, name = "Disabled State", widthDp = 300) -@Composable -fun TextButtonPreview() { - Column(Modifier.padding(16.dp)) { - TextButton(text = "시작하기", onClick = {}, enabled = false) - - Spacer(modifier = Modifier.height(12.dp)) - - TextButton(text = "시작하기", onClick = {}, enabled = true) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/textbutton/TextButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/textbutton/TextButton.kt deleted file mode 100644 index 246bd943..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/atom/textbutton/TextButton.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.atom.textbutton - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsPressedAsState -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - -@Composable -fun TextButton( - modifier: Modifier = Modifier, - text: String, - onClick: () -> Unit, - enabled: Boolean = true, - defaultBackgroundColor: Color = Color(0xFF1A237E), - pressedBackgroundColor: Color = Color(0xFF0D123F), - disabledBackgroundColor: Color = Color(0xFFF0F0F0), - defaultTextColor: Color = Color.White, - pressedTextColor: Color = Color(0xFFA0A0A0), - disabledTextColor: Color = Color(0xFFB0B0B0), -) { - val interactionSource = remember { MutableInteractionSource() } - val isPressed by interactionSource.collectIsPressedAsState() - - val backgroundColor = when { - !enabled -> disabledBackgroundColor - isPressed -> pressedBackgroundColor - else -> defaultBackgroundColor - } - - val textColor = when { - !enabled -> disabledTextColor - isPressed -> pressedTextColor - else -> defaultTextColor - } - - Box( - modifier = modifier - .fillMaxWidth() - .height(56.dp) - .clip(RoundedCornerShape(12.dp)) - .background(backgroundColor) - .clickable( - enabled = enabled, - onClick = onClick, - interactionSource = interactionSource, - indication = null, - ), - contentAlignment = Alignment.Center, - ) { - Text( - text = text, - style = TextStyle( - color = textColor, - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - ), - ) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/block/selectbutton/OnBoardingSelectButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/block/selectbutton/OnBoardingSelectButton.kt deleted file mode 100644 index 8cd00394..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/block/selectbutton/OnBoardingSelectButton.kt +++ /dev/null @@ -1,98 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.block.selectbutton - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsPressedAsState -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -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.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - -@Composable -fun OnBoardingSelectButton( - modifier: Modifier = Modifier, - iconResourceId: Int? = null, - title: String, - description: String?, - onClick: () -> Unit, - selected: Boolean = false, -) { - val interactionSource = remember { MutableInteractionSource() } - val isPressed by interactionSource.collectIsPressedAsState() - - val backgroundColor = if (isPressed || selected) Color(0xFFD6E0F5) else Color.White - val contentColor = Color(0xFF70737C) - - Row( - modifier = modifier - .fillMaxWidth() - .clip(RoundedCornerShape(12.dp)) - .background(backgroundColor) - .clickable( - interactionSource = interactionSource, - indication = null, - onClick = onClick, - ) - .padding(horizontal = 20.dp, vertical = 16.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - iconResourceId?.let { - Image( - painter = painterResource(iconResourceId), - contentDescription = title, - modifier = Modifier - .size(40.dp) - .background(Color(0xFFE5E7EB), RoundedCornerShape(8.dp)), - contentScale = ContentScale.Inside, - ) - - Spacer(modifier = Modifier.width(12.dp)) - } - - Column( - verticalArrangement = Arrangement.Center, - ) { - Text( - text = title, - style = TextStyle( - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - color = contentColor, - ), - ) - - description?.let { - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = description, - style = TextStyle( - fontSize = 14.sp, - color = contentColor.copy(alpha = 0.7f), - ), - ) - } - } - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/block/selectbutton/Preview.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/block/selectbutton/Preview.kt deleted file mode 100644 index 1be4f2fa..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/block/selectbutton/Preview.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.threegap.bitnagil.presentation.onboarding.component.block.selectbutton - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp - -@Preview(showBackground = true) -@Composable -fun OnBoardingSelectButtonPreview() { - Column { - OnBoardingSelectButton( - title = "루틴명", - description = "세부 루틴 한 줄 설명", - onClick = {}, - iconResourceId = android.R.drawable.ic_menu_search, - ) - - Spacer(modifier = Modifier.height(12.dp)) - - OnBoardingSelectButton( - title = "루틴명", - description = "세부 루틴 한 줄 설명", - onClick = {}, - ) - - Spacer(modifier = Modifier.height(12.dp)) - - OnBoardingSelectButton( - title = "루틴명", - description = null, - onClick = {}, - ) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingAbstractTemplate.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingAbstractTemplate.kt index 119225d8..a61bf22d 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingAbstractTemplate.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingAbstractTemplate.kt @@ -1,24 +1,25 @@ package com.threegap.bitnagil.presentation.onboarding.component.template -import androidx.compose.foundation.background +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box 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.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp +import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.R import com.threegap.bitnagil.presentation.onboarding.model.OnBoardingAbstractTextItem @Composable @@ -37,12 +38,14 @@ fun OnBoardingAbstractTemplate( } } - val titleTextStyle = TextStyle(fontSize = 20.sp) - Column( modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 20.dp, top = 32.dp), ) { - Text(title, style = titleTextStyle) + Text( + text = title, + color = BitnagilTheme.colors.navy500, + style = BitnagilTheme.typography.title2Bold, + ) Spacer(modifier = Modifier.height(10.dp)) @@ -51,9 +54,23 @@ fun OnBoardingAbstractTemplate( OnBoardingAbstractText(onBoardingAbstractTextList = onBoardingAbstractTextItemList) } - Spacer(modifier = Modifier.height(36.dp)) + Spacer(modifier = Modifier.height(83.dp)) - Box(modifier = Modifier.fillMaxWidth().weight(1f).background(color = Color(0xFFC2C4C8))) + Box( + modifier = Modifier + .fillMaxWidth() + .weight(1f), + contentAlignment = Alignment.TopCenter, + ) { + Image( + painter = painterResource(R.drawable.onboarding_character), + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier + .padding(horizontal = 15.dp) + .aspectRatio(295f / 280f), + ) + } } } @@ -62,12 +79,18 @@ private fun OnBoardingAbstractText( onBoardingAbstractTextList: List, ) { val annotatedString = buildAnnotatedString { - withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { + withStyle(style = BitnagilTheme.typography.body2SemiBold.toSpanStyle()) { append("• ") } onBoardingAbstractTextList.forEach { - withStyle(style = SpanStyle(fontWeight = if (it.isBold) FontWeight.Bold else null)) { + withStyle( + style = if (it.isBold) { + BitnagilTheme.typography.body2SemiBold.toSpanStyle() + } else { + BitnagilTheme.typography.body2Regular.toSpanStyle() + }, + ) { append(it.text) } } @@ -75,6 +98,7 @@ private fun OnBoardingAbstractText( Text( text = annotatedString, - style = TextStyle(fontSize = 14.sp), + color = BitnagilTheme.colors.coolGray30, + style = BitnagilTheme.typography.body2Regular, ) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt index 35553015..634dbf5c 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/onboarding/component/template/OnBoardingSelectTemplate.kt @@ -1,27 +1,20 @@ package com.threegap.bitnagil.presentation.onboarding.component.template -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box 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.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.threegap.bitnagil.presentation.onboarding.component.atom.textbutton.TextButton -import com.threegap.bitnagil.presentation.onboarding.component.block.selectbutton.OnBoardingSelectButton +import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.atom.BitnagilSelectButton +import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButton +import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButtonColor import com.threegap.bitnagil.presentation.onboarding.model.OnBoardingItem @Composable @@ -35,18 +28,23 @@ fun OnBoardingSelectTemplate( onClickItem: (String) -> Unit, onClickSkip: (() -> Unit)? = null, ) { - val titleTextStyle = TextStyle(fontSize = 20.sp) - val subTextStyle = TextStyle(fontSize = 14.sp) - Column( modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 20.dp, top = 32.dp), ) { - Text(title, style = titleTextStyle) + Text( + text = title, + color = BitnagilTheme.colors.navy500, + style = BitnagilTheme.typography.title2Bold, + ) subText?.let { Spacer(modifier = Modifier.height(10.dp)) - Text(subText, style = subTextStyle) + Text( + text = subText, + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.body2Medium, + ) } Spacer(modifier = Modifier.height(28.dp)) @@ -58,21 +56,21 @@ fun OnBoardingSelectTemplate( .verticalScroll(state = scrollState), ) { for (item in items) { - OnBoardingSelectButton( - modifier = Modifier.padding(bottom = 12.dp), + BitnagilSelectButton( title = item.title, description = item.description, onClick = { onClickItem(item.id) }, selected = item.selected, + modifier = Modifier.padding(bottom = 12.dp), ) } } Spacer(modifier = Modifier.height(12.dp)) - TextButton( + BitnagilTextButton( text = "다음", onClick = onClickNextButton, enabled = nextButtonEnable, @@ -81,23 +79,13 @@ fun OnBoardingSelectTemplate( onClickSkip?.let { Spacer(modifier = Modifier.height(10.dp)) - Box( - modifier = Modifier - .fillMaxWidth() - .height(54.dp) - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - onClick = onClickSkip, - ), - contentAlignment = Alignment.Center, - ) { - Text( - text = "건너뛰기", - style = TextStyle(textDecoration = TextDecoration.Underline), - textAlign = TextAlign.Center, - ) - } + BitnagilTextButton( + text = "건너뛰기", + onClick = onClickSkip, + colors = BitnagilTextButtonColor.skip(), + textStyle = BitnagilTheme.typography.body2Regular, + textDecoration = TextDecoration.Underline, + ) } } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt index ba98326a..87a12508 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/RecommendRoutineScreen.kt @@ -1,9 +1,7 @@ package com.threegap.bitnagil.presentation.recommendroutine import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -17,9 +15,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.KeyboardArrowDown -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -30,6 +25,10 @@ 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.R +import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.recommendroutine.component.atom.RecommendCategoryChip import com.threegap.bitnagil.presentation.recommendroutine.component.block.EmotionRecommendRoutineButton import com.threegap.bitnagil.presentation.recommendroutine.component.block.RecommendRoutineItem @@ -81,19 +80,7 @@ private fun RecommendRoutineScreen( .fillMaxSize() .background(BitnagilTheme.colors.white), ) { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .height(54.dp) - .fillMaxWidth() - .padding(vertical = 15.dp), - ) { - Text( - text = "추천 루틴", - color = BitnagilTheme.colors.coolGray5, - style = BitnagilTheme.typography.title3SemiBold, - ) - } + BitnagilTopBar(title = "추천 루틴") Spacer(modifier = Modifier.height(16.dp)) @@ -137,10 +124,7 @@ private fun RecommendRoutineScreen( horizontalArrangement = Arrangement.spacedBy(5.dp), modifier = Modifier .fillMaxHeight() - // todo: 리플효과 제거하기 - .clickable { - onShowDifficultyBottomSheet() - }, + .clickableWithoutRipple { onShowDifficultyBottomSheet() }, ) { Text( text = uiState.selectedDifficulty?.displayName ?: "난이도 선택", @@ -149,10 +133,9 @@ private fun RecommendRoutineScreen( modifier = Modifier.padding(start = 10.dp), ) - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.KeyboardArrowDown, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_down_arrow, + tint = BitnagilTheme.colors.coolGray60, modifier = Modifier .padding(end = 13.dp) .size(16.dp), diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/atom/RecommendCategoryChip.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/atom/RecommendCategoryChip.kt index 873feb15..7bbe86d9 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/atom/RecommendCategoryChip.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/atom/RecommendCategoryChip.kt @@ -1,7 +1,6 @@ package com.threegap.bitnagil.presentation.recommendroutine.component.atom import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -14,6 +13,7 @@ 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.modifier.clickableWithoutRipple @Composable fun RecommendCategoryChip( @@ -29,8 +29,7 @@ fun RecommendCategoryChip( color = if (!isSelected) BitnagilTheme.colors.coolGray99 else BitnagilTheme.colors.navy500, shape = RoundedCornerShape(20.dp), ) - // todo: 리플효과 제거하기 - .clickable { onCategorySelected() } + .clickableWithoutRipple(onClick = onCategorySelected) .padding( vertical = 9.dp, horizontal = 14.dp, diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/EmotionRecommendRoutineButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/EmotionRecommendRoutineButton.kt index 02de5027..7848c406 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/EmotionRecommendRoutineButton.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/EmotionRecommendRoutineButton.kt @@ -2,16 +2,12 @@ package com.threegap.bitnagil.presentation.recommendroutine.component.block import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -19,6 +15,9 @@ 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 EmotionRecommendRoutineButton( @@ -39,17 +38,15 @@ fun EmotionRecommendRoutineButton( color = BitnagilTheme.colors.white, shape = RoundedCornerShape(12.dp), ) - // todo: 리플효과 제거하기 - .clickable { onClick() } + .clickableWithoutRipple { onClick() } .padding( vertical = 16.dp, horizontal = 24.dp, ), ) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.Add, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_plus, + tint = BitnagilTheme.colors.navy400, modifier = Modifier .padding(end = 10.dp) .size(20.dp), diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.kt index 29371ead..fe38f153 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/block/RecommendRoutineItem.kt @@ -1,17 +1,14 @@ package com.threegap.bitnagil.presentation.recommendroutine.component.block import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column 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.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -19,6 +16,9 @@ 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 RecommendRoutineItem( @@ -36,10 +36,7 @@ fun RecommendRoutineItem( color = BitnagilTheme.colors.lightBlue75, shape = RoundedCornerShape(12.dp), ) - // todo: 리플 효과 제거하기 - .clickable( - onClick = onAddRoutineClick, - ) + .clickableWithoutRipple(onClick = onAddRoutineClick) .padding( vertical = 16.dp, horizontal = 20.dp, @@ -62,10 +59,10 @@ fun RecommendRoutineItem( ) } - // todo: icon 디자인 수정하기 - Icon( - imageVector = Icons.Default.Add, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_plus, + tint = BitnagilTheme.colors.navy400, + modifier = Modifier.size(32.dp), ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RoutineDifficultyBottomSheet.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RoutineDifficultyBottomSheet.kt index b0d98b83..f46f66d2 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RoutineDifficultyBottomSheet.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/recommendroutine/component/template/RoutineDifficultyBottomSheet.kt @@ -1,14 +1,10 @@ package com.threegap.bitnagil.presentation.recommendroutine.component.template -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -17,6 +13,9 @@ 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 import com.threegap.bitnagil.presentation.recommendroutine.type.RecommendRoutineDifficulty @OptIn(ExperimentalMaterial3Api::class) @@ -70,8 +69,7 @@ private fun DifficultyOption( Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier - // todo: 리플효과 제거하기 - .clickable { onClick() } + .clickableWithoutRipple { onClick() } .padding(vertical = 8.dp), ) { Text( @@ -82,10 +80,8 @@ private fun DifficultyOption( ) if (isSelected) { - // todo: 아이콘 변경하기 - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_check, tint = BitnagilTheme.colors.orange500, ) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt index 23ae4f8e..068dd103 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/SettingScreen.kt @@ -3,7 +3,6 @@ package com.threegap.bitnagil.presentation.setting import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -11,7 +10,6 @@ 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.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll @@ -26,10 +24,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.block.BitnagilOptionButton +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar import com.threegap.bitnagil.presentation.common.flow.collectAsEffect import com.threegap.bitnagil.presentation.setting.component.atom.settingtitle.SettingTitle import com.threegap.bitnagil.presentation.setting.component.atom.toggleswitch.ToggleSwitch -import com.threegap.bitnagil.presentation.setting.component.block.settingrowbutton.SettingRowButton import com.threegap.bitnagil.presentation.setting.model.mvi.SettingSideEffect import com.threegap.bitnagil.presentation.setting.model.mvi.SettingState @@ -79,26 +78,11 @@ private fun SettingScreen( .fillMaxSize() .background(color = BitnagilTheme.colors.white), ) { - Box( - modifier = Modifier - .height(54.dp) - .fillMaxWidth(), - ) { - Box( - modifier = Modifier - .padding(start = 10.dp) - .size(36.dp) - .background(BitnagilTheme.colors.black) - .align(Alignment.CenterStart) - .clickable(onClick = onClickBack), - ) - - Text( - "설정", - modifier = Modifier.align(Alignment.Center), - style = BitnagilTheme.typography.title3SemiBold, - ) - } + BitnagilTopBar( + title = "설정", + showBackButton = true, + onBackClick = onClickBack, + ) val scrollState = rememberScrollState() Column( @@ -151,8 +135,16 @@ private fun SettingScreen( verticalAlignment = Alignment.CenterVertically, ) { Row { - Text("버전 ", style = BitnagilTheme.typography.body1Regular) - Text(state.version, style = BitnagilTheme.typography.body1SemiBold) + Text( + text = "버전 ", + color = BitnagilTheme.colors.black, + style = BitnagilTheme.typography.body1Regular, + ) + Text( + text = state.version, + color = BitnagilTheme.colors.black, + style = BitnagilTheme.typography.body1SemiBold, + ) } if (state.version == state.latestVersion) { Text( @@ -180,9 +172,15 @@ private fun SettingScreen( } } - SettingRowButton(text = "서비스 이용약관", onClick = onClickTermsOfService) + BitnagilOptionButton( + title = "서비스 이용약관", + onClick = onClickTermsOfService, + ) - SettingRowButton(text = "개인정보 처리방침", onClick = onClickPrivacyPolicy) + BitnagilOptionButton( + title = "개인정보 처리방침", + onClick = onClickPrivacyPolicy, + ) Spacer(modifier = Modifier.height(6.dp)) @@ -192,9 +190,15 @@ private fun SettingScreen( SettingTitle("계정") - SettingRowButton(text = "로그아웃", onClick = onClickLogout) + BitnagilOptionButton( + title = "로그아웃", + onClick = onClickLogout, + ) - SettingRowButton(text = "탈퇴하기", onClick = onClickWithdrawal) + BitnagilOptionButton( + title = "탈퇴하기", + onClick = onClickWithdrawal, + ) } } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/settingrowbutton/SettingRowButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/settingrowbutton/SettingRowButton.kt deleted file mode 100644 index ae00deac..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/setting/component/block/settingrowbutton/SettingRowButton.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.threegap.bitnagil.presentation.setting.component.block.settingrowbutton - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.threegap.bitnagil.designsystem.BitnagilTheme - -@Composable -fun SettingRowButton( - onClick: () -> Unit, - text: String, -) { - Row( - modifier = Modifier - .height(48.dp) - .clickable(onClick = onClick) - .padding(start = 16.dp, end = 4.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text, - style = BitnagilTheme.typography.body1Regular, - modifier = Modifier.weight(1f), - ) - - Box( - modifier = Modifier - .padding(end = 10.dp) - .size(36.dp) - .background(BitnagilTheme.colors.black), - ) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/TermsAgreementScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/TermsAgreementScreen.kt index 820fd36b..c940705c 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/TermsAgreementScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/TermsAgreementScreen.kt @@ -1,34 +1,25 @@ package com.threegap.bitnagil.presentation.terms import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.Button -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color 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.atom.BitnagilTextButton +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar import com.threegap.bitnagil.presentation.terms.component.TermsAgreementItem +import com.threegap.bitnagil.presentation.terms.component.ToggleAllAgreementsItem import com.threegap.bitnagil.presentation.terms.model.TermsAgreementIntent import com.threegap.bitnagil.presentation.terms.model.TermsAgreementSideEffect import com.threegap.bitnagil.presentation.terms.model.TermsAgreementState @@ -109,71 +100,33 @@ private fun TermsAgreementScreen( Column( modifier = modifier .fillMaxSize() - .background(Color.White), + .background(BitnagilTheme.colors.white), ) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(54.dp), - ) { - Icon( - imageVector = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = "뒤로가기", - modifier = Modifier - .align(Alignment.CenterStart) - .clickable( - onClick = onBackButtonClick, - ), - ) + BitnagilTopBar( + title = "약관 동의", + showBackButton = true, + onBackClick = onBackButtonClick, + ) - Text( - text = "이용약관", - color = Color.Black, - modifier = Modifier.align(Alignment.Center), - ) - } + Spacer(modifier = Modifier.height(48.dp)) Column( - modifier = Modifier - .padding( - top = 48.dp, - ) - .padding(horizontal = 16.dp), + modifier = Modifier.padding(horizontal = 16.dp), ) { Text( text = "빛나길 이용을 위해\n필수 약관에 동의해 주세요.", + color = BitnagilTheme.colors.navy500, + style = BitnagilTheme.typography.title2Bold, ) - Spacer( - modifier = Modifier.height(28.dp), + Spacer(modifier = Modifier.height(28.dp)) + + ToggleAllAgreementsItem( + isAllAgreed = uiState.isAllAgreed, + onToggleAllAgreements = onToggleAllAgreements, ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp), - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 8.dp) - .background( - color = Color.LightGray, - shape = RoundedCornerShape(10.dp), - ) - .clickable { onToggleAllAgreements(!uiState.isAllAgreed) } - .padding( - vertical = 12.dp, - horizontal = 16.dp, - ), - ) { - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, - tint = if (uiState.isAllAgreed) Color.Black else Color.Gray, - modifier = Modifier.size(24.dp), - ) - Text( - text = "전체동의", - ) - } + Spacer(modifier = Modifier.height(8.dp)) TermsAgreementItem( title = "(필수) 서비스 이용약관 동의", @@ -198,18 +151,17 @@ private fun TermsAgreementScreen( ) } - Button( + Spacer(modifier = Modifier.weight(1f)) + + BitnagilTextButton( + text = "시작하기", onClick = onStartButtonClick, enabled = uiState.submitEnabled, modifier = Modifier .fillMaxWidth() - .padding( - horizontal = 16.dp, - vertical = 16.dp, - ), - ) { - Text("시작하기") - } + .padding(horizontal = 16.dp) + .padding(bottom = 20.dp), + ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/TermsAgreementItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/TermsAgreementItem.kt index 23c96227..43705d03 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/TermsAgreementItem.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/TermsAgreementItem.kt @@ -1,15 +1,11 @@ package com.threegap.bitnagil.presentation.terms.component -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box 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.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -18,10 +14,13 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextDecoration 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 TermsAgreementItem( @@ -35,6 +34,7 @@ fun TermsAgreementItem( Box( modifier = modifier .fillMaxWidth() + .height(40.dp) .padding( vertical = 10.dp, horizontal = 20.dp, @@ -45,24 +45,29 @@ fun TermsAgreementItem( horizontalArrangement = Arrangement.spacedBy(18.dp), modifier = Modifier .align(Alignment.CenterStart) - .clickable(onClick = onCheckedChange), + .clickableWithoutRipple { onCheckedChange() }, ) { - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, - tint = if (isChecked) Color.Black else Color.Gray, - modifier = Modifier.size(16.dp), + BitnagilIcon( + id = R.drawable.ic_check, + tint = if (isChecked) BitnagilTheme.colors.navy500 else BitnagilTheme.colors.navy100, + ) + + Text( + text = title, + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.body2Medium, ) - Text(text = title) } if (showMore) { Text( text = "더보기", + color = BitnagilTheme.colors.coolGray50, + style = BitnagilTheme.typography.caption1UnderlineSemiBold, textDecoration = TextDecoration.Underline, modifier = Modifier .align(Alignment.CenterEnd) - .clickable(onClick = onClickShowMore), + .clickableWithoutRipple { onClickShowMore() }, ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/ToggleAllAgreementsItem.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/ToggleAllAgreementsItem.kt new file mode 100644 index 00000000..5fadeec7 --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/terms/component/ToggleAllAgreementsItem.kt @@ -0,0 +1,76 @@ +package com.threegap.bitnagil.presentation.terms.component + +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.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +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 ToggleAllAgreementsItem( + isAllAgreed: Boolean, + onToggleAllAgreements: (Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + val backgroundColor = if (isAllAgreed) BitnagilTheme.colors.lightBlue75 else BitnagilTheme.colors.coolGray99 + val iconColor = if (isAllAgreed) BitnagilTheme.colors.navy500 else BitnagilTheme.colors.navy100 + val textColor = if (isAllAgreed) BitnagilTheme.colors.navy500 else BitnagilTheme.colors.coolGray50 + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = modifier + .fillMaxWidth() + .height(52.dp) + .background( + color = backgroundColor, + shape = RoundedCornerShape(10.dp), + ) + .clickableWithoutRipple { onToggleAllAgreements(!isAllAgreed) } + .padding( + vertical = 12.dp, + horizontal = 16.dp, + ), + ) { + BitnagilIcon( + id = R.drawable.ic_check, + tint = iconColor, + modifier = Modifier.size(24.dp), + ) + Text( + text = "전체동의", + color = textColor, + style = BitnagilTheme.typography.subtitle1SemiBold, + ) + } +} + +@Preview +@Composable +private fun ToggleAllAgreementsItemPreview() { + var isAllAgreed by remember { mutableStateOf(false) } + + ToggleAllAgreementsItem( + isAllAgreed = isAllAgreed, + onToggleAllAgreements = { + isAllAgreed = !isAllAgreed + }, + ) +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/webview/BitnagilWebViewScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/webview/BitnagilWebViewScreen.kt index 542f94a6..8c196396 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/webview/BitnagilWebViewScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/webview/BitnagilWebViewScreen.kt @@ -6,28 +6,17 @@ import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column 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.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material3.Icon -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar @Composable fun BitnagilWebViewScreen( @@ -76,33 +65,11 @@ fun BitnagilWebViewScreen( .fillMaxSize() .background(BitnagilTheme.colors.white), ) { - Box( - modifier = Modifier - .height(54.dp) - .fillMaxWidth(), - ) { - // todo: 아이콘 수정하기 - Icon( - imageVector = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = null, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(start = 4.dp) - // todo: 리플효과 제거하기 - .clickable( - onClick = onBackClick, - ) - .size(36.dp), - ) - - Text( - text = title, - color = BitnagilTheme.colors.coolGray10, - style = BitnagilTheme.typography.title3SemiBold, - modifier = Modifier - .align(Alignment.Center), - ) - } + BitnagilTopBar( + title = title, + showBackButton = true, + onBackClick = onBackClick, + ) AndroidView( modifier = Modifier.fillMaxSize(), diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/WriteRoutineScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/WriteRoutineScreen.kt index 074c1909..09765eb2 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/WriteRoutineScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/WriteRoutineScreen.kt @@ -1,10 +1,6 @@ package com.threegap.bitnagil.presentation.writeroutine -import android.R -import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -12,7 +8,6 @@ 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.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -22,16 +17,18 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment 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 androidx.hilt.navigation.compose.hiltViewModel 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.component.atom.BitnagilTextButton +import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar import com.threegap.bitnagil.presentation.common.flow.collectAsEffect import com.threegap.bitnagil.presentation.writeroutine.component.atom.namefield.NameField import com.threegap.bitnagil.presentation.writeroutine.component.atom.selectcell.SelectCell import com.threegap.bitnagil.presentation.writeroutine.component.atom.strokebutton.StrokeButton -import com.threegap.bitnagil.presentation.writeroutine.component.atom.textbutton.TextButton import com.threegap.bitnagil.presentation.writeroutine.component.atom.tooltipbutton.TooltipButton import com.threegap.bitnagil.presentation.writeroutine.component.block.labeledcheckbox.LabeledCheckBox import com.threegap.bitnagil.presentation.writeroutine.component.template.TimePickerBottomSheet @@ -102,32 +99,11 @@ private fun WriteRoutineScreen( Column( modifier = Modifier.fillMaxSize().background(color = BitnagilTheme.colors.white), ) { - Box( - modifier = Modifier - .fillMaxWidth() - .height(54.dp), - ) { - Box( - modifier = Modifier - .padding(start = 4.dp) - .align(alignment = Alignment.CenterStart) - .size(36.dp) - .clickable(onClick = onClickBack), - contentAlignment = Alignment.Center, - ) { - Image( - painter = painterResource(R.drawable.ic_media_play), - contentDescription = null, - modifier = Modifier.size(24.dp), - ) - } - - Text( - if (state.writeRoutineType == WriteRoutineType.ADD) "루틴 등록" else "루틴 수정", - modifier = Modifier.align(alignment = Alignment.Center), - style = BitnagilTheme.typography.title3SemiBold, - ) - } + BitnagilTopBar( + title = if (state.writeRoutineType == WriteRoutineType.ADD) "루틴 등록" else "루틴 수정", + showBackButton = true, + onBackClick = onClickBack, + ) Column( modifier = Modifier @@ -168,6 +144,7 @@ private fun WriteRoutineScreen( ) { Text( "세부 루틴", + color = BitnagilTheme.colors.coolGray10, style = BitnagilTheme.typography.body1SemiBold, ) @@ -187,10 +164,9 @@ private fun WriteRoutineScreen( modifier = Modifier.height(52.dp).fillMaxWidth().padding(start = 24.dp, end = 16.dp), verticalAlignment = Alignment.CenterVertically, ) { - Image( - painter = painterResource(R.drawable.ic_media_play), - contentDescription = null, - modifier = Modifier.size(20.dp), + BitnagilIcon( + id = R.drawable.ic_plus, + tint = BitnagilTheme.colors.navy400, ) Spacer(modifier = Modifier.width(10.dp)) @@ -329,10 +305,9 @@ private fun WriteRoutineScreen( Spacer(modifier = Modifier.weight(1f)) - Image( - painter = painterResource(R.drawable.ic_media_play), - contentDescription = null, - modifier = Modifier.size(20.dp), + BitnagilIcon( + id = R.drawable.ic_down_arrow, + tint = BitnagilTheme.colors.navy400, ) } } @@ -341,11 +316,12 @@ private fun WriteRoutineScreen( Spacer(modifier = Modifier.height(54.dp)) } - TextButton( - modifier = Modifier.fillMaxWidth().padding(start = 16.dp, end = 16.dp, bottom = 14.dp), + BitnagilTextButton( text = "등록하기", onClick = onClickRegister, enabled = state.registerButtonEnabled, + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, top = 14.dp, bottom = 14.dp), ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/namefield/NameField.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/namefield/NameField.kt index fc86c2b2..d22be270 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/namefield/NameField.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/namefield/NameField.kt @@ -6,19 +6,17 @@ 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.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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 NameField( @@ -53,13 +51,11 @@ fun NameField( } if (onClickRemove != null) { - IconButton( - onClick = onClickRemove, - modifier = Modifier.size(24.dp), + Box( + modifier = Modifier.clickableWithoutRipple(onClick = onClickRemove), ) { - Icon( - imageVector = Icons.Default.Close, - contentDescription = "제거", + BitnagilIcon( + id = R.drawable.ic_close, tint = BitnagilTheme.colors.coolGray80, ) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/selectcell/SelectCell.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/selectcell/SelectCell.kt index 40e04fa1..5659e162 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/selectcell/SelectCell.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/selectcell/SelectCell.kt @@ -1,7 +1,6 @@ package com.threegap.bitnagil.presentation.writeroutine.component.atom.selectcell import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.height import androidx.compose.foundation.shape.RoundedCornerShape @@ -12,6 +11,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple @Composable fun SelectCell( @@ -27,9 +27,13 @@ fun SelectCell( color = if (selected) BitnagilTheme.colors.lightBlue100 else Color.Transparent, shape = RoundedCornerShape(12.dp), ) - .clickable(onClick = onClick), + .clickableWithoutRipple(onClick = onClick), contentAlignment = Alignment.Center, ) { - Text(text, style = BitnagilTheme.typography.body2Medium) + Text( + text = text, + color = BitnagilTheme.colors.navy400, + style = BitnagilTheme.typography.body2Medium, + ) } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/strokebutton/StrokeButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/strokebutton/StrokeButton.kt index fe7baccb..270f6e63 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/strokebutton/StrokeButton.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/strokebutton/StrokeButton.kt @@ -1,7 +1,6 @@ package com.threegap.bitnagil.presentation.writeroutine.component.atom.strokebutton import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape @@ -12,6 +11,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple class StrokeButton { companion object { @@ -77,11 +77,11 @@ private fun StrokeButtonFrame( modifier = modifier .clip(RoundedCornerShape(12.dp)) .border( - width = 1.5.dp, + width = 1.dp, color = borderColor, shape = RoundedCornerShape(12.dp), ) - .clickable(enabled = enabled, onClick = onClick), + .clickableWithoutRipple(enabled = enabled, onClick = onClick), contentAlignment = Alignment.Center, ) { content() diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/Preview.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/Preview.kt deleted file mode 100644 index f12a5d9a..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/Preview.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.threegap.bitnagil.presentation.writeroutine.component.atom.textbutton - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp - -@Preview(showBackground = true, name = "Disabled State", widthDp = 300) -@Composable -fun TextButtonPreview() { - Column(Modifier.padding(16.dp)) { - TextButton(text = "시작하기", onClick = {}, enabled = false) - - Spacer(modifier = Modifier.height(12.dp)) - - TextButton(text = "시작하기", onClick = {}, enabled = true) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt deleted file mode 100644 index 64e52a51..00000000 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/textbutton/TextButton.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.threegap.bitnagil.presentation.writeroutine.component.atom.textbutton - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.collectIsPressedAsState -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - -@Composable -fun TextButton( - modifier: Modifier = Modifier, - text: String, - onClick: () -> Unit, - enabled: Boolean = true, - defaultBackgroundColor: Color = Color(0xFF1A237E), - pressedBackgroundColor: Color = Color(0xFF0D123F), - disabledBackgroundColor: Color = Color(0xFFF0F0F0), - defaultTextColor: Color = Color.White, - pressedTextColor: Color = Color(0xFFA0A0A0), - disabledTextColor: Color = Color(0xFFB0B0B0), -) { - val interactionSource = remember { MutableInteractionSource() } - val isPressed by interactionSource.collectIsPressedAsState() - - val backgroundColor = when { - !enabled -> disabledBackgroundColor - isPressed -> pressedBackgroundColor - else -> defaultBackgroundColor - } - - val textColor = when { - !enabled -> disabledTextColor - isPressed -> pressedTextColor - else -> defaultTextColor - } - - Box( - modifier = modifier - .fillMaxWidth() - .height(56.dp) - .clip(RoundedCornerShape(12.dp)) - .background(backgroundColor) - .clickable( - enabled = enabled, - onClick = onClick, - interactionSource = interactionSource, - indication = null, - ), - contentAlignment = Alignment.Center, - ) { - Text( - text = text, - style = TextStyle( - color = textColor, - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - ), - ) - } -} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/tooltipbutton/TooltipButton.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/tooltipbutton/TooltipButton.kt index bb81bac4..28ce9368 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/tooltipbutton/TooltipButton.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/atom/tooltipbutton/TooltipButton.kt @@ -1,8 +1,6 @@ package com.threegap.bitnagil.presentation.writeroutine.component.atom.tooltipbutton -import android.R import androidx.compose.foundation.Canvas -import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -30,12 +28,14 @@ import androidx.compose.ui.graphics.Path import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize 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 import com.threegap.bitnagil.presentation.writeroutine.component.atom.tooltipbutton.model.TooltipDirection import com.threegap.bitnagil.presentation.writeroutine.component.atom.tooltipbutton.model.TooltipPositionProvider import kotlinx.coroutines.launch @@ -91,12 +91,11 @@ fun TooltipButton( }, state = tooltipState, ) { - Image( - painter = painterResource(R.drawable.ic_menu_info_details), - contentDescription = null, + BitnagilIcon( + id = R.drawable.ic_tooltip, + tint = BitnagilTheme.colors.navy200, modifier = Modifier - .size(24.dp) - .clickable { + .clickableWithoutRipple { coroutineScope.launch { tooltipState.show() } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/block/labeledcheckbox/LabeledCheckBox.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/block/labeledcheckbox/LabeledCheckBox.kt index ba33575d..573a6172 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/block/labeledcheckbox/LabeledCheckBox.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/block/labeledcheckbox/LabeledCheckBox.kt @@ -2,7 +2,6 @@ package com.threegap.bitnagil.presentation.writeroutine.component.block.labeledc import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -15,6 +14,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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 LabeledCheckBox( @@ -24,7 +26,7 @@ fun LabeledCheckBox( modifier: Modifier = Modifier, ) { Row( - modifier = modifier.clickable(onClick = onClick), + modifier = modifier.clickableWithoutRipple(onClick = onClick), verticalAlignment = Alignment.CenterVertically, ) { Box( @@ -39,7 +41,15 @@ fun LabeledCheckBox( shape = RoundedCornerShape(4.dp), color = if (checked) BitnagilTheme.colors.navy500 else BitnagilTheme.colors.coolGray95, ), - ) + contentAlignment = Alignment.Center, + ) { + if (checked) { + BitnagilIcon( + id = R.drawable.ic_check, + tint = BitnagilTheme.colors.white, + ) + } + } Spacer(modifier = Modifier.width(6.dp)) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/template/TimePickerBottomSheet.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/template/TimePickerBottomSheet.kt index 50a7086a..2ca93c5a 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/template/TimePickerBottomSheet.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/writeroutine/component/template/TimePickerBottomSheet.kt @@ -19,8 +19,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import com.threegap.bitnagil.designsystem.BitnagilTheme +import com.threegap.bitnagil.designsystem.component.atom.BitnagilTextButton import com.threegap.bitnagil.presentation.R -import com.threegap.bitnagil.presentation.onboarding.component.atom.textbutton.TextButton import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @@ -104,7 +104,7 @@ fun TimePickerBottomSheetContent( }, ) - TextButton( + BitnagilTextButton( modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 14.dp), text = "저장", onClick = {