diff --git a/app/src/main/java/com/threegap/bitnagil/MainActivity.kt b/app/src/main/java/com/threegap/bitnagil/MainActivity.kt index 15fbabc0..aa01ab53 100644 --- a/app/src/main/java/com/threegap/bitnagil/MainActivity.kt +++ b/app/src/main/java/com/threegap/bitnagil/MainActivity.kt @@ -9,6 +9,7 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment @@ -53,7 +54,8 @@ class MainActivity : ComponentActivity() { state = globalToast, modifier = Modifier .align(Alignment.BottomCenter) - .padding(bottom = 100.dp), + .navigationBarsPadding() + .padding(bottom = if (mainNavigator.hasBottomNavigationBarRoute()) 80.dp else 16.dp), ) } } diff --git a/app/src/main/java/com/threegap/bitnagil/MainNavigator.kt b/app/src/main/java/com/threegap/bitnagil/MainNavigator.kt index 275fd455..18a1a4db 100644 --- a/app/src/main/java/com/threegap/bitnagil/MainNavigator.kt +++ b/app/src/main/java/com/threegap/bitnagil/MainNavigator.kt @@ -1,8 +1,12 @@ package com.threegap.bitnagil import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.navigation.NavDestination +import androidx.navigation.NavDestination.Companion.hasRoute import androidx.navigation.NavHostController +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController class MainNavigator( @@ -10,12 +14,27 @@ class MainNavigator( ) { val startDestination = Route.Splash + private val currentDestination: NavDestination? + @Composable get() { + val currentEntry by navController.currentBackStackEntryAsState() + return currentEntry?.destination + } + internal fun navigateToHomeAndClearStack() = navController.navigate(Route.Home) { popUpTo(0) { inclusive = true } } + + @Composable + internal fun hasBottomNavigationBarRoute(): Boolean { + val destination = currentDestination + return when { + destination?.hasRoute() == true -> true + else -> false + } + } } @Composable diff --git a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt index 490f9092..ccac2b68 100644 --- a/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt +++ b/core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt @@ -8,9 +8,8 @@ import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically 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.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape @@ -33,38 +32,34 @@ import kotlinx.coroutines.delay @Composable fun BitnagilToastMessage( + @DrawableRes id: Int, text: String, modifier: Modifier = Modifier, - @DrawableRes id: Int? = null, ) { - Box( + Row( modifier = modifier + .padding(horizontal = 16.dp) .background( - color = BitnagilTheme.colors.navy400, - shape = RoundedCornerShape(8.dp), + color = BitnagilTheme.colors.coolGray30, + shape = RoundedCornerShape(12.dp), ) - .padding(vertical = 10.dp, horizontal = 20.dp), - contentAlignment = Alignment.Center, + .fillMaxWidth() + .padding(vertical = 14.dp, horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - if (id != null) { - BitnagilIcon( - id = id, - tint = BitnagilTheme.colors.error, - modifier = Modifier - .padding(end = 4.dp) - .size(24.dp), - ) - } - Text( - text = text, - color = BitnagilTheme.colors.white, - style = BitnagilTheme.typography.body2Medium, - textAlign = TextAlign.Center, - ) - } + BitnagilIcon( + id = id, + tint = null, + modifier = Modifier.size(24.dp), + ) + + Text( + text = text, + color = BitnagilTheme.colors.white, + style = BitnagilTheme.typography.body2Medium, + textAlign = TextAlign.Center, + ) } } @@ -98,17 +93,17 @@ fun BitnagilToastContainer( class BitnagilToastState { private var _text by mutableStateOf("") - private var _icon by mutableStateOf(null) + private var _icon by mutableIntStateOf(0) private var _isVisible by mutableStateOf(false) private var _toastId by mutableIntStateOf(0) private var _lastShowTime = 0L val text: String get() = _text - val icon: Int? get() = _icon + val icon: Int get() = _icon val isVisible: Boolean get() = _isVisible val toastId: Int get() = _toastId - fun show(text: String, icon: Int? = null) { + fun show(text: String, icon: Int) { if (shouldPreventDuplicateShow(text, icon)) { return } @@ -124,7 +119,7 @@ class BitnagilToastState { return _text == text && _icon == icon && currentTime - _lastShowTime < 500L } - private fun showToast(text: String, icon: Int?) { + private fun showToast(text: String, icon: Int) { _text = text _icon = icon _isVisible = true @@ -139,16 +134,8 @@ fun rememberBitnagilToast(): BitnagilToastState = remember { BitnagilToastState( @Preview @Composable private fun BitnagilToastMessagePreview() { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - BitnagilToastMessage( - text = "버튼을 한 번 더 누르면 종료됩니다.", - id = R.drawable.ic_warning, - ) - - BitnagilToastMessage( - text = "루틴 완료 상태 저장에 실패했어요.\n다시 시도해 주세요.", - ) - } + BitnagilToastMessage( + text = "버튼을 한 번 더 누르면 종료됩니다.", + id = R.drawable.ic_warning, + ) } diff --git a/core/designsystem/src/main/res/drawable/ic_warning.xml b/core/designsystem/src/main/res/drawable/ic_warning.xml index 2cbbc64b..395cc6ed 100644 --- a/core/designsystem/src/main/res/drawable/ic_warning.xml +++ b/core/designsystem/src/main/res/drawable/ic_warning.xml @@ -5,8 +5,29 @@ android:viewportHeight="24"> + android:pathData="M4.622,15.21C4.472,15.47 4.332,15.71 4.202,15.93C4.052,16.2 3.632,16.28 3.512,16.5C3.362,16.79 3.132,17 3.052,17.22C2.942,17.53 2.892,17.87 2.912,18.11C2.942,18.39 3.002,18.76 3.142,19C3.282,19.24 3.612,19.41 3.842,19.58C4.032,19.72 4.372,19.55 4.702,19.61C4.932,19.65 5.172,19.78 5.492,19.79C5.742,19.8 6.012,19.8 6.312,19.8C6.562,19.8 6.842,19.63 7.142,19.63C7.542,19.63 7.542,19.79 7.942,19.79C8.342,19.79 8.342,19.88 8.752,19.88C9.162,19.88 9.152,20.12 9.562,20.12C9.972,20.12 9.962,20.12 10.372,20.12C10.781,20.12 10.771,19.79 11.182,19.79C11.592,19.79 11.582,19.9 11.991,19.9C12.401,19.9 12.392,19.99 12.802,19.99C13.212,19.99 13.201,20.09 13.611,20.09C14.021,20.09 14.012,19.74 14.422,19.74C14.832,19.74 14.832,20.03 15.231,20.03C15.632,20.03 15.642,20.04 16.042,20.04C16.441,20.04 16.451,19.77 16.851,19.77C17.152,19.77 17.431,19.6 17.681,19.59C17.992,19.59 18.271,19.87 18.511,19.85C18.831,19.84 19.111,19.85 19.341,19.81C19.671,19.75 19.751,19.41 19.941,19.27C20.171,19.1 20.601,19.16 20.742,18.92C20.882,18.68 21.031,18.38 21.062,18.1C21.091,17.86 21.132,17.5 21.011,17.19C20.931,16.97 20.581,16.81 20.431,16.52C20.322,16.3 20.132,16.09 19.982,15.82C19.851,15.6 19.851,15.28 19.701,15.02C19.501,14.67 19.521,14.66 19.312,14.31C19.101,13.96 18.761,14.16 18.552,13.81C18.341,13.46 18.701,13.26 18.501,12.91C18.302,12.56 18.351,12.53 18.152,12.18C17.951,11.83 17.751,11.94 17.552,11.59C17.351,11.24 17.242,11.3 17.042,10.95C16.841,10.6 16.861,10.59 16.662,10.24C16.462,9.89 16.462,9.89 16.261,9.54C16.062,9.19 16.281,9.06 16.081,8.71C15.882,8.36 15.651,8.49 15.451,8.14C15.252,7.79 15.601,7.58 15.401,7.23C15.201,6.88 15.151,6.9 14.951,6.55C14.802,6.29 14.571,6.1 14.441,5.88C14.281,5.61 13.872,5.55 13.741,5.34C13.571,5.07 13.741,4.6 13.592,4.42C13.382,4.17 13.071,4.02 12.851,3.92C12.592,3.8 12.262,3.99 11.991,3.99C11.722,3.99 11.542,4.15 11.281,4.26C11.061,4.36 10.672,4.22 10.451,4.48C10.302,4.66 10.292,4.99 10.111,5.26C9.982,5.47 9.702,5.62 9.552,5.89C9.422,6.11 9.242,6.32 9.082,6.58C8.882,6.93 9.012,7 8.802,7.35C8.592,7.7 8.852,7.84 8.642,8.19C8.432,8.54 8.132,8.36 7.932,8.71C7.732,9.06 7.662,9.02 7.462,9.37C7.262,9.72 7.162,9.66 6.962,10.01C6.762,10.36 7.042,10.52 6.842,10.87C6.642,11.22 6.712,11.26 6.512,11.61C6.312,11.96 6.392,12.01 6.192,12.35C5.992,12.69 5.842,12.62 5.642,12.97C5.442,13.32 5.242,13.2 5.032,13.56C4.822,13.92 4.812,13.93 4.692,14.32C4.562,14.74 4.792,14.83 4.592,15.18L4.622,15.21Z" /> + android:fillColor="#00000000" + android:pathData="M4.622,15.21C4.472,15.47 4.332,15.71 4.202,15.93C4.052,16.2 3.632,16.28 3.512,16.5C3.362,16.79 3.132,17 3.052,17.22C2.942,17.53 2.892,17.87 2.912,18.11C2.942,18.39 3.002,18.76 3.142,19C3.282,19.24 3.612,19.41 3.842,19.58C4.032,19.72 4.372,19.55 4.702,19.61C4.932,19.65 5.172,19.78 5.492,19.79C5.742,19.8 6.012,19.8 6.312,19.8C6.562,19.8 6.842,19.63 7.142,19.63C7.542,19.63 7.542,19.79 7.942,19.79C8.342,19.79 8.342,19.88 8.752,19.88C9.162,19.88 9.152,20.12 9.562,20.12C9.972,20.12 9.962,20.12 10.372,20.12C10.781,20.12 10.771,19.79 11.182,19.79C11.592,19.79 11.582,19.9 11.991,19.9C12.401,19.9 12.392,19.99 12.802,19.99C13.212,19.99 13.201,20.09 13.611,20.09C14.021,20.09 14.012,19.74 14.422,19.74C14.832,19.74 14.832,20.03 15.231,20.03C15.632,20.03 15.642,20.04 16.042,20.04C16.441,20.04 16.451,19.77 16.851,19.77C17.152,19.77 17.431,19.6 17.681,19.59C17.992,19.59 18.271,19.87 18.511,19.85C18.831,19.84 19.111,19.85 19.341,19.81C19.671,19.75 19.751,19.41 19.941,19.27C20.171,19.1 20.601,19.16 20.742,18.92C20.882,18.68 21.031,18.38 21.062,18.1C21.091,17.86 21.132,17.5 21.011,17.19C20.931,16.97 20.581,16.81 20.431,16.52C20.322,16.3 20.132,16.09 19.982,15.82C19.851,15.6 19.851,15.28 19.701,15.02C19.501,14.67 19.521,14.66 19.312,14.31C19.101,13.96 18.761,14.16 18.552,13.81C18.341,13.46 18.701,13.26 18.501,12.91C18.302,12.56 18.351,12.53 18.152,12.18C17.951,11.83 17.751,11.94 17.552,11.59C17.351,11.24 17.242,11.3 17.042,10.95C16.841,10.6 16.861,10.59 16.662,10.24C16.462,9.89 16.462,9.89 16.261,9.54C16.062,9.19 16.281,9.06 16.081,8.71C15.882,8.36 15.651,8.49 15.451,8.14C15.252,7.79 15.601,7.58 15.401,7.23C15.201,6.88 15.151,6.9 14.951,6.55C14.802,6.29 14.571,6.1 14.441,5.88C14.281,5.61 13.872,5.55 13.741,5.34C13.571,5.07 13.741,4.6 13.592,4.42C13.382,4.17 13.071,4.02 12.851,3.92C12.592,3.8 12.262,3.99 11.991,3.99C11.722,3.99 11.542,4.15 11.281,4.26C11.061,4.36 10.672,4.22 10.451,4.48C10.302,4.66 10.292,4.99 10.111,5.26C9.982,5.47 9.702,5.62 9.552,5.89C9.422,6.11 9.242,6.32 9.082,6.58C8.882,6.93 9.012,7 8.802,7.35C8.592,7.7 8.852,7.84 8.642,8.19C8.432,8.54 8.132,8.36 7.932,8.71C7.732,9.06 7.662,9.02 7.462,9.37C7.262,9.72 7.162,9.66 6.962,10.01C6.762,10.36 7.042,10.52 6.842,10.87C6.642,11.22 6.712,11.26 6.512,11.61C6.312,11.96 6.392,12.01 6.192,12.35C5.992,12.69 5.842,12.62 5.642,12.97C5.442,13.32 5.242,13.2 5.032,13.56C4.822,13.92 4.812,13.93 4.692,14.32C4.562,14.74 4.792,14.83 4.592,15.18L4.622,15.21Z" + android:strokeWidth="2" + android:strokeColor="#FF6868" + android:strokeLineCap="round" + android:strokeLineJoin="round" /> + + + diff --git a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt index 1a7f3cd2..8dec08b2 100644 --- a/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt +++ b/domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt @@ -35,7 +35,7 @@ enum class DayOfWeek { } fun List.formatRepeatDays(): String { - if (this.isEmpty()) return "반복 없음" + if (this.isEmpty()) return "x" return this.sortedBy { it.ordinal } .joinToString(", ") { it.toKoreanShort() } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt index b6eb4b24..22ffb3df 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt @@ -11,11 +11,11 @@ object GlobalBitnagilToast { _toastStateRef = WeakReference(toastState) } - fun show(text: String, icon: Int? = null) { + fun show(text: String, icon: Int) { _toastStateRef?.get()?.show(text, icon) } - fun showCheck(text: String) = show(text, R.drawable.ic_check) + fun showCheck(text: String) = show(text, R.drawable.ic_check_circle_orange) fun showWarning(text: String) = show(text, R.drawable.ic_warning) } 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 997ddd47..3ac06c15 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 @@ -26,7 +26,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.threegap.bitnagil.designsystem.BitnagilTheme import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.common.flow.collectAsEffect -import com.threegap.bitnagil.presentation.common.toast.GlobalBitnagilToast import com.threegap.bitnagil.presentation.home.component.template.CollapsibleHomeHeader import com.threegap.bitnagil.presentation.home.component.template.EmptyRoutineView import com.threegap.bitnagil.presentation.home.component.template.RoutineSection @@ -64,14 +63,6 @@ fun HomeScreenContainer( is HomeSideEffect.NavigateToRoutineList -> { navigateToRoutineList(sideEffect.selectedDate) } - - is HomeSideEffect.ShowToastWithIcon -> { - GlobalBitnagilToast.showCheck(sideEffect.message) - } - - is HomeSideEffect.ShowToast -> { - GlobalBitnagilToast.show(sideEffect.message) - } } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt index 14bcccdf..3754c7ad 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt @@ -132,7 +132,6 @@ class HomeViewModel @Inject constructor( } is HomeIntent.RoutineToggleCompletionFailure -> { - sendSideEffect(HomeSideEffect.ShowToast("루틴 완료 상태 저장에 실패했어요.\n다시 시도해 주세요.")) null } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt index 925da1ce..6e727ef5 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt @@ -3,8 +3,6 @@ package com.threegap.bitnagil.presentation.home.model import com.threegap.bitnagil.presentation.common.mviviewmodel.MviSideEffect sealed interface HomeSideEffect : MviSideEffect { - data class ShowToast(val message: String) : HomeSideEffect - data class ShowToastWithIcon(val message: String) : HomeSideEffect data object NavigateToGuide : HomeSideEffect data object NavigateToRegisterRoutine : HomeSideEffect data object NavigateToEmotion : HomeSideEffect diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt index f84a3835..7cbe1bb1 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt @@ -11,6 +11,7 @@ private val koreanLocale = Locale.KOREAN private val monthYearFormatter = DateTimeFormatter.ofPattern("yyyy년 M월", koreanLocale) private val executionTimeFormatter12 = DateTimeFormatter.ofPattern("a h:mm", koreanLocale) private val executionTimeFormatter24 = DateTimeFormatter.ofPattern("HH:mm", koreanLocale) +private val shortDateFormatter = DateTimeFormatter.ofPattern("yy.MM.dd") fun LocalDate.getCurrentWeekDays(): List = (0..6).map { this.with(DayOfWeek.MONDAY).plusDays(it.toLong()) } @@ -47,3 +48,11 @@ fun String.formatExecutionTime12Hour(): String = } catch (e: Exception) { "시간 미정" } + +fun String.toShortDateFormat(): String = + try { + val date = LocalDate.parse(this) + date.format(shortDateFormatter) + } catch (e: Exception) { + this + } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt index f0a911c5..131868be 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt @@ -22,6 +22,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.threegap.bitnagil.designsystem.BitnagilTheme import com.threegap.bitnagil.designsystem.component.block.BitnagilTopBar import com.threegap.bitnagil.presentation.common.flow.collectAsEffect +import com.threegap.bitnagil.presentation.common.toast.GlobalBitnagilToast import com.threegap.bitnagil.presentation.routinelist.component.template.DeleteConfirmBottomSheet import com.threegap.bitnagil.presentation.routinelist.component.template.EditConfirmBottomSheet import com.threegap.bitnagil.presentation.routinelist.component.template.EmptyRoutineListView @@ -44,10 +45,9 @@ fun RoutineListScreenContainer( viewModel.sideEffectFlow.collectAsEffect { sideEffect -> when (sideEffect) { + is RoutineListSideEffect.ShowToast -> GlobalBitnagilToast.showCheck(sideEffect.message) is RoutineListSideEffect.NavigateToBack -> navigateToBack() - is RoutineListSideEffect.NavigateToAddRoutine -> { - navigateToAddRoutine() - } + is RoutineListSideEffect.NavigateToAddRoutine -> navigateToAddRoutine() is RoutineListSideEffect.NavigateToEditRoutine -> { navigateToEditRoutine(sideEffect.routineId, sideEffect.updateRoutineFromNowDate) } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt index c350b862..e61e2e57 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt @@ -72,9 +72,7 @@ class RoutineListViewModel @Inject constructor( } is RoutineListIntent.OnRegisterRoutineClick -> { - sendSideEffect( - RoutineListSideEffect.NavigateToAddRoutine, - ) + sendSideEffect(RoutineListSideEffect.NavigateToAddRoutine) null } @@ -103,6 +101,14 @@ class RoutineListViewModel @Inject constructor( } null } + + is RoutineListIntent.OnSuccessDeletedRoutine -> { + sendSideEffect(RoutineListSideEffect.ShowToast("삭제가 완료되었습니다.")) + state.copy( + isLoading = false, + deleteConfirmBottomSheetVisible = false, + ) + } } return newState @@ -133,8 +139,8 @@ class RoutineListViewModel @Inject constructor( viewModelScope.launch { deleteRoutineUseCase(selectedRoutine.routineId).fold( onSuccess = { - sendIntent(RoutineListIntent.HideDeleteConfirmBottomSheet) - sendIntent(RoutineListIntent.UpdateLoading(false)) + fetchRoutines() + sendIntent(RoutineListIntent.OnSuccessDeletedRoutine) }, onFailure = { Log.e("RoutineListViewModel", "루틴 삭제 실패: ${it.message}") @@ -150,8 +156,8 @@ class RoutineListViewModel @Inject constructor( viewModelScope.launch { deleteRoutineForDayUseCase(selectedRoutine.routineId).fold( onSuccess = { - sendIntent(RoutineListIntent.HideDeleteConfirmBottomSheet) - sendIntent(RoutineListIntent.UpdateLoading(false)) + fetchRoutines() + sendIntent(RoutineListIntent.OnSuccessDeletedRoutine) }, onFailure = { Log.e("RoutineListViewModel", "루틴 삭제 실패: ${it.message}") diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt index 70b748fe..8606c081 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt @@ -14,6 +14,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.threegap.bitnagil.designsystem.BitnagilTheme @@ -33,6 +34,13 @@ fun RoutineDetailsCard( onDeleteClick: () -> Unit, modifier: Modifier = Modifier, ) { + val infoTextStyle = BitnagilTheme.typography.body2Medium.copy( + lineHeightStyle = LineHeightStyle( + alignment = LineHeightStyle.Alignment.Center, + trim = LineHeightStyle.Trim.None, + ), + ) + Column( modifier = modifier .background( @@ -67,12 +75,14 @@ fun RoutineDetailsCard( Spacer(modifier = Modifier.weight(1f)) - BitnagilIconButton( - id = R.drawable.ic_edit, - onClick = onEditClick, - tint = null, - paddingValues = PaddingValues(12.dp), - ) + if (!routine.routineDeletedYn) { + BitnagilIconButton( + id = R.drawable.ic_edit, + onClick = onEditClick, + tint = null, + paddingValues = PaddingValues(12.dp), + ) + } BitnagilIconButton( id = R.drawable.ic_trash, @@ -97,14 +107,14 @@ fun RoutineDetailsCard( Text( text = "세부 루틴", color = BitnagilTheme.colors.coolGray40, - style = BitnagilTheme.typography.body2Medium, + style = infoTextStyle, ) routine.subRoutineNames.forEach { name -> Text( text = "• $name", color = BitnagilTheme.colors.coolGray40, - style = BitnagilTheme.typography.body2Medium, + style = infoTextStyle, ) } } @@ -124,17 +134,17 @@ fun RoutineDetailsCard( Text( text = "반복: ${routine.repeatDay.formatRepeatDays()}", color = BitnagilTheme.colors.coolGray40, - style = BitnagilTheme.typography.body2Medium, + style = infoTextStyle, ) Text( - text = "기간: ", + text = "기간: ${routine.formattedDateRange}", color = BitnagilTheme.colors.coolGray40, - style = BitnagilTheme.typography.body2Medium, + style = infoTextStyle, ) Text( text = "시간: ${routine.executionTime}", color = BitnagilTheme.colors.coolGray40, - style = BitnagilTheme.typography.body2Medium, + style = infoTextStyle, ) } } @@ -150,6 +160,9 @@ private fun RoutineDetailsCardPreview() { repeatDay = listOf(DayOfWeek.MONDAY, DayOfWeek.TUESDAY), executionTime = "00:00:00", routineDate = "2025-08-15", + startDate = "2025-08-15", + endDate = "2025-08-25", + routineDeletedYn = false, subRoutineNames = listOf("어쩌구", "저쩌구", "얼씨구"), recommendedRoutineType = null, ), diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt index 418838c0..f0f5559c 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt @@ -15,4 +15,5 @@ sealed class RoutineListIntent : MviIntent { data object OnRegisterRoutineClick : RoutineListIntent() data object OnApplyTodayClick : RoutineListIntent() data object OnApplyTomorrowClick : RoutineListIntent() + data object OnSuccessDeletedRoutine : RoutineListIntent() } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListSideEffect.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListSideEffect.kt index 0e137f93..002762ae 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListSideEffect.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListSideEffect.kt @@ -6,4 +6,5 @@ sealed interface RoutineListSideEffect : MviSideEffect { data object NavigateToBack : RoutineListSideEffect data object NavigateToAddRoutine : RoutineListSideEffect data class NavigateToEditRoutine(val routineId: String, val updateRoutineFromNowDate: Boolean) : RoutineListSideEffect + data class ShowToast(val message: String) : RoutineListSideEffect } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt index ab442c42..0796f915 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt @@ -9,6 +9,7 @@ import com.threegap.bitnagil.domain.routine.model.DayOfWeek import com.threegap.bitnagil.domain.routine.model.RecommendedRoutineType import com.threegap.bitnagil.domain.routine.model.Routine import com.threegap.bitnagil.presentation.home.util.formatExecutionTime12Hour +import com.threegap.bitnagil.presentation.home.util.toShortDateFormat import kotlinx.parcelize.Parcelize @Parcelize @@ -18,9 +19,15 @@ data class RoutineUiModel( val repeatDay: List, val executionTime: String, val routineDate: String, + val startDate: String, + val endDate: String, + val routineDeletedYn: Boolean, val subRoutineNames: List, val recommendedRoutineType: RecommendedRoutineType?, -) : Parcelable +) : Parcelable { + val formattedDateRange: String + get() = "${startDate.toShortDateFormat()} - ${endDate.toShortDateFormat()}" +} fun Routine.toUiModel(): RoutineUiModel = RoutineUiModel( @@ -29,6 +36,9 @@ fun Routine.toUiModel(): RoutineUiModel = repeatDay = this.repeatDay, executionTime = this.executionTime.formatExecutionTime12Hour(), routineDate = this.routineDate, + startDate = this.startDate, + endDate = this.endDate, + routineDeletedYn = this.routineDeletedYn, subRoutineNames = this.subRoutineNames, recommendedRoutineType = this.recommendedRoutineType, )