diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategory.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategory.kt new file mode 100644 index 0000000..13d5868 --- /dev/null +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategory.kt @@ -0,0 +1,59 @@ +package com.dkin.chevit.presentation.checklist.category + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.fragment.app.viewModels +import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController +import com.dkin.chevit.core.mvi.MVIComposeFragment +import com.dkin.chevit.presentation.common.model.getCategoryTypeByName +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class EditCategory : + MVIComposeFragment() { + override val viewModel: EditCategoryViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + return ComposeView(requireContext()).apply { + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + EditCategoryScreen( + viewModel = viewModel, + onClickBack = { findNavController().popBackStack() } + ) + } + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val planId = arguments?.getString("planId") + val categoryId = arguments?.getString("categoryId") + val title = arguments?.getString("title") + val type = arguments?.getString("type") + if (planId == null || categoryId == null || title == null || type == null) { + //todo alert + findNavController().popBackStack() + } else { + viewModel.initState(planId, categoryId, title, getCategoryTypeByName(type)) + } + } + + override fun processEffect(effect: EditCategoryEffect) { + when (effect) { + else -> {} + } + } + + override fun processState(state: EditCategoryState) {} + +} \ No newline at end of file diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryContract.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryContract.kt new file mode 100644 index 0000000..3992bca --- /dev/null +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryContract.kt @@ -0,0 +1,23 @@ +package com.dkin.chevit.presentation.checklist.category + +import com.dkin.chevit.core.mvi.ViewEffect +import com.dkin.chevit.core.mvi.ViewIntent +import com.dkin.chevit.core.mvi.ViewState +import com.dkin.chevit.presentation.common.model.CategoryType + +sealed interface EditCategoryIntent : ViewIntent { +} + +data class EditCategoryState( + val planId: String, + val categoryId: String, + val title: String, + val type: CategoryType +) : ViewState { + companion object { + fun empty() = EditCategoryState("", "", "", CategoryType.REQUIRES) + } +} + +sealed interface EditCategoryEffect : ViewEffect { +} \ No newline at end of file diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryScreen.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryScreen.kt new file mode 100644 index 0000000..3b79db0 --- /dev/null +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryScreen.kt @@ -0,0 +1,191 @@ +package com.dkin.chevit.presentation.checklist.category + +import androidx.compose.foundation.Image +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 +import androidx.compose.foundation.layout.PaddingValues +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.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +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.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.dkin.chevit.presentation.common.model.CategoryType +import com.dkin.chevit.presentation.resource.ChevitButtonFillMedium +import com.dkin.chevit.presentation.resource.ChevitTextField +import com.dkin.chevit.presentation.resource.ChevitTheme +import com.dkin.chevit.presentation.resource.getCategoryIconResId +import com.dkin.chevit.presentation.resource.icon.ChevitIcon +import com.dkin.chevit.presentation.resource.icon.IconArrowLeftLine +import com.dkin.chevit.presentation.resource.icon.IconCloseCircleFill +import com.dkin.chevit.presentation.resource.util.clickableNoRipple + +@Composable +fun EditCategoryScreen( + viewModel: EditCategoryViewModel, + onClickBack: () -> Unit +) { + val state = viewModel.state.collectAsState().value + var input by remember { mutableStateOf(state.title) } + var selectedCategory by remember { mutableStateOf(state.type) } + var isValidInput by remember { mutableStateOf(true) } + var saveable by remember { mutableStateOf(false) } + + LaunchedEffect(input) { + isValidInput = input.length < 9 + saveable = input.isNotBlank() && isValidInput + } + LaunchedEffect(selectedCategory) { + saveable = input.isNotBlank() && isValidInput + } + + val categories = CategoryType.values() + + Column( + modifier = Modifier.fillMaxSize() + ) { + TopBar(modifier = Modifier.fillMaxWidth(), onClickBack = onClickBack) + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 24.dp), + ) { + Spacer(modifier = Modifier.height(25.dp)) + Text( + text = "새 카테고리", + style = ChevitTheme.typhography.headlineMedium.copy(color = ChevitTheme.colors.textPrimary), + ) + Spacer(modifier = Modifier.height(18.dp)) + Text( + text = "카테고리 제목을 입력해 주세요.", + style = ChevitTheme.typhography.bodyMedium.copy(color = ChevitTheme.colors.grey6), + ) + Spacer(modifier = Modifier.height(8.dp)) + ChevitTextField( + modifier = Modifier.fillMaxWidth(), + value = input, + isInputError = !isValidInput, + onValueChange = { + input = it + }, + placeholder = { + Text( + modifier = Modifier, + text = "ex. 기내 아이템", + style = ChevitTheme.typhography.bodyLarge.copy(color = ChevitTheme.colors.grey4), + ) + }, + trailingIcon = { + if (input.isNotEmpty()) { + Icon( + modifier = Modifier + .size(20.dp) + .clickableNoRipple { + input = "" + }, + imageVector = ChevitIcon.IconCloseCircleFill, + contentDescription = "", + ) + } + } + ) + if (!isValidInput) { + Spacer(modifier = Modifier.height(2.dp)) + Text( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp), + text = "최대 8글자까지 입력해주세요.", + style = ChevitTheme.typhography.bodySmall.copy(color = ChevitTheme.colors.statusError), + ) + } + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = "아이콘", + style = ChevitTheme.typhography.headlineMedium.copy(color = ChevitTheme.colors.textPrimary), + ) + LazyVerticalGrid( + modifier = Modifier.weight(1f), + columns = GridCells.Fixed(5), + horizontalArrangement = Arrangement.spacedBy(22.dp), + verticalArrangement = Arrangement.spacedBy(22.dp), + contentPadding = PaddingValues(vertical = 18.dp) + ) { + items(categories) { category -> + val isSelected = category == selectedCategory + Box( + modifier = Modifier + .size(48.dp) + .background(color = ChevitTheme.colors.grey0, shape = CircleShape) + .border( + width = if (isSelected) 1.dp else (-1).dp, + color = ChevitTheme.colors.grey10, + shape = CircleShape, + ) + .clickable { selectedCategory = category }, + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(id = category.getCategoryIconResId()), + contentDescription = "" + ) + } + } + } + ChevitButtonFillMedium( + modifier = Modifier.fillMaxWidth(), + enabled = saveable, + onClick = { selectedCategory.let { viewModel.saveCategory(input, it) } } + ) { + Text(text = "수정하기") + } + Spacer(modifier = Modifier.height(24.dp)) + } + } +} + +@Composable +private fun TopBar(modifier: Modifier, onClickBack: () -> Unit) { + Box( + modifier = modifier + .height(58.dp) + .padding(vertical = 16.dp, horizontal = 24.dp), + contentAlignment = Alignment.Center + ) { + Icon( + modifier = Modifier + .align(Alignment.CenterStart) + .clickableNoRipple { onClickBack() }, + imageVector = ChevitIcon.IconArrowLeftLine, + contentDescription = "", + ) + Text( + modifier = Modifier.align(Alignment.Center), + text = "카테고리 수정하기", + textAlign = TextAlign.Center, + style = ChevitTheme.typhography.headlineMedium.copy(color = ChevitTheme.colors.textPrimary) + ) + } +} diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryViewModel.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryViewModel.kt new file mode 100644 index 0000000..2c4e4e4 --- /dev/null +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/category/EditCategoryViewModel.kt @@ -0,0 +1,28 @@ +package com.dkin.chevit.presentation.checklist.category + +import com.dkin.chevit.core.mvi.MVIViewModel +import com.dkin.chevit.presentation.common.model.CategoryType +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class EditCategoryViewModel @Inject constructor() : + MVIViewModel() { + override fun createInitialState(): EditCategoryState = EditCategoryState.empty() + + override suspend fun processIntent(intent: EditCategoryIntent) { + when (intent) { + else -> {} + } + } + + fun initState(planId: String,categoryId: String, title: String, type: CategoryType) { + setState { + EditCategoryState(planId, categoryId, title, type) + } + } + + fun saveCategory(title: String, category: CategoryType) { + //todo + } +} \ No newline at end of file diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/Checklist.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/Checklist.kt index 851c8b9..49a5ca6 100644 --- a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/Checklist.kt +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/Checklist.kt @@ -8,14 +8,17 @@ import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.window.DialogProperties import androidx.fragment.app.viewModels +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.dialog import androidx.navigation.compose.rememberNavController import androidx.navigation.findNavController +import androidx.navigation.navArgument import com.dkin.chevit.core.mvi.MVIComposeFragment import com.dkin.chevit.presentation.checklist.R import com.dkin.chevit.presentation.checklist.main.contents.FloatingContents +import com.dkin.chevit.presentation.checklist.main.contents.MoreCategoryBottomSheet import com.dkin.chevit.presentation.checklist.main.contents.SaveTemplateContents import com.dkin.chevit.presentation.deeplink.DeepLink import com.dkin.chevit.presentation.deeplink.deepLink @@ -66,7 +69,10 @@ class Checklist : MVIComposeFragment + navController.navigate("categoryMore/${id}?title=${title}?type=${type.name}") + } ) } dialog( @@ -94,6 +100,38 @@ class Checklist : MVIComposeFragment Unit, navigateAddCategory: () -> Unit, - openFloatingContents: () -> Unit + openFloatingContents: () -> Unit, + openCategoryMoreSheet: (id: String, title: String, type: CategoryType) -> Unit, ) { val checklistState by viewModel.state.collectAsState() var showCountryInfo by remember { mutableStateOf(true) } @@ -153,6 +155,7 @@ fun ChecklistScreen( CategoryListContents( categories = checklistState.categories, onClickCategory = { id -> viewModel.onClickCategory(id) }, + onLongClickCategory = {id, title, type -> openCategoryMoreSheet(id, title, type)} ) } } diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/ChecklistViewModel.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/ChecklistViewModel.kt index ab6819a..2e48b54 100644 --- a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/ChecklistViewModel.kt +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/ChecklistViewModel.kt @@ -32,6 +32,10 @@ class ChecklistViewModel @Inject constructor() : setEffect { ChecklistEffect.NavigateToCategory(id) } } + fun deleteCategory(planId: String, categoryId: String) { + //todo + } + fun bringTemplate() { setEffect { ChecklistEffect.NavigateToBringTemplate } } diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/CategoryListContents.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/CategoryListContents.kt index 9b5f913..8b30741 100644 --- a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/CategoryListContents.kt +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/CategoryListContents.kt @@ -1,8 +1,9 @@ package com.dkin.chevit.presentation.checklist.main.contents +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -28,16 +29,19 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.dkin.chevit.presentation.checklist.main.ChecklistState +import com.dkin.chevit.presentation.common.model.CategoryType import com.dkin.chevit.presentation.resource.ChevitTheme import com.dkin.chevit.presentation.resource.getCategoryIconResId import com.dkin.chevit.presentation.resource.icon.ChevitIcon import com.dkin.chevit.presentation.resource.icon.TemplateCheckOff import com.dkin.chevit.presentation.resource.icon.TemplateCheckOn +@OptIn(ExperimentalFoundationApi::class) @Composable fun CategoryListContents( categories: List, - onClickCategory: (categoryId: String) -> Unit + onClickCategory: (categoryId: String) -> Unit, + onLongClickCategory: (categoryId: String, title: String, type: CategoryType) -> Unit ) { Column( modifier = Modifier @@ -56,7 +60,10 @@ fun CategoryListContents( modifier = Modifier .clip(RoundedCornerShape(8.dp)) .background(color = if (completed) ChevitTheme.colors.grey0 else ChevitTheme.colors.grey1) - .clickable { onClickCategory(category.categoryId) } + .combinedClickable( + onClick = {onClickCategory(category.categoryId)}, + onLongClick = {onLongClickCategory(category.categoryId, category.title, category.categoryType)} + ) .padding(vertical = 12.dp, horizontal = 12.dp), horizontalAlignment = Alignment.CenterHorizontally ) { diff --git a/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/MoreCategoryBottomSheet.kt b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/MoreCategoryBottomSheet.kt new file mode 100644 index 0000000..f26ed4a --- /dev/null +++ b/presentation/checklist/src/main/java/com/dkin/chevit/presentation/checklist/main/contents/MoreCategoryBottomSheet.kt @@ -0,0 +1,92 @@ +package com.dkin.chevit.presentation.checklist.main.contents + +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.width +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.TextOverflow +import androidx.compose.ui.unit.dp +import com.dkin.chevit.presentation.resource.ChevitBottomsheet +import com.dkin.chevit.presentation.resource.ChevitTheme +import com.dkin.chevit.presentation.resource.icon.ChevitIcon +import com.dkin.chevit.presentation.resource.icon.IconCheckboxCircleFill + +@Composable +fun MoreCategoryBottomSheet( + title: String, + navigateEditItem: () -> Unit, + deleteItem: () -> Unit, + onClose: () -> Unit +) { + ChevitBottomsheet( + modifier = Modifier.fillMaxSize(), + onClickBackground = onClose + ) { + Column(modifier = Modifier.fillMaxWidth()) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Image( + imageVector = ChevitIcon.IconCheckboxCircleFill, + contentDescription = "", + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = title, + style = ChevitTheme.typhography.headlineMedium.copy(color = ChevitTheme.colors.textPrimary), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + } + Spacer(modifier = Modifier.height(4.dp)) + Column( + modifier = Modifier.fillMaxWidth().clickable { navigateEditItem() } + ) { + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "수정하기", + style = ChevitTheme.typhography.bodyLarge.copy(color = ChevitTheme.colors.textPrimary), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + Spacer(modifier = Modifier.height(16.dp)) + } + Box( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(color = ChevitTheme.colors.grey0) + ) + Column( + modifier = Modifier.fillMaxWidth().clickable { deleteItem() } + ) { + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "삭제하기", + style = ChevitTheme.typhography.bodyLarge.copy(color = ChevitTheme.colors.textPrimary), + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) + Spacer(modifier = Modifier.height(16.dp)) + } + Box( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(color = ChevitTheme.colors.grey0) + ) + } + } +} \ No newline at end of file diff --git a/presentation/checklist/src/main/res/navigation/nav_checklist.xml b/presentation/checklist/src/main/res/navigation/nav_checklist.xml index ea37e5f..cb68ce6 100644 --- a/presentation/checklist/src/main/res/navigation/nav_checklist.xml +++ b/presentation/checklist/src/main/res/navigation/nav_checklist.xml @@ -34,4 +34,23 @@ android:label="AddCategory"> + + + + + + + + diff --git a/presentation/common/src/main/java/com/dkin/chevit/presentation/common/model/CategoryType.kt b/presentation/common/src/main/java/com/dkin/chevit/presentation/common/model/CategoryType.kt index 9cdc873..e35c2a8 100644 --- a/presentation/common/src/main/java/com/dkin/chevit/presentation/common/model/CategoryType.kt +++ b/presentation/common/src/main/java/com/dkin/chevit/presentation/common/model/CategoryType.kt @@ -16,4 +16,9 @@ enum class CategoryType(val title: String) { SWIMMING("수영"), CLOTHES("의류"), ETC("기타"), +} + +fun getCategoryTypeByName(name: String): CategoryType { + val colors = CategoryType.values() + return colors.find { it.name == name } ?: CategoryType.REQUIRES } \ No newline at end of file diff --git a/presentation/deeplink/src/main/java/com/dkin/chevit/presentation/deeplink/DeepLink.kt b/presentation/deeplink/src/main/java/com/dkin/chevit/presentation/deeplink/DeepLink.kt index 732d626..7036f29 100644 --- a/presentation/deeplink/src/main/java/com/dkin/chevit/presentation/deeplink/DeepLink.kt +++ b/presentation/deeplink/src/main/java/com/dkin/chevit/presentation/deeplink/DeepLink.kt @@ -47,6 +47,15 @@ sealed interface DeepLink { override val deepLink: String = "$SCHEME://addCategory/$planId" } + data class EditCategory( + val planId: String, + val categoryId: String, + val title: String, + val type: String + ) : DeepLink { + override val deepLink: String = "$SCHEME://editCategory/$planId/$categoryId/$title/$type" + } + data class TemplateDetail(val id: String) : DeepLink { override val deepLink: String = "$SCHEME://template/$id" } diff --git a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/MoreTemplateBottomSheet.kt b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/MoreBottomSheet.kt similarity index 99% rename from presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/MoreTemplateBottomSheet.kt rename to presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/MoreBottomSheet.kt index 4ec52fc..0e49fc3 100644 --- a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/MoreTemplateBottomSheet.kt +++ b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/MoreBottomSheet.kt @@ -23,7 +23,7 @@ import com.dkin.chevit.presentation.resource.icon.ChevitIcon import com.dkin.chevit.presentation.resource.icon.IconCheckboxCircleFill @Composable -fun MoreTemplateBottomSheet( +fun MoreBottomSheet( title: String, navigateEditItem: () -> Unit, deleteItem: () -> Unit, diff --git a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/TemplateTabContents.kt b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/TemplateTabContents.kt index 1601025..6dec121 100644 --- a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/TemplateTabContents.kt +++ b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/TemplateTabContents.kt @@ -53,7 +53,7 @@ fun TemplateTabContents( val title = it.arguments?.getString("title") ?: "" val color = it.arguments?.getString("color") ?: "" - MoreTemplateBottomSheet( + MoreBottomSheet( title = title, navigateEditItem = { navController.navigate("editTemplate/${planId}?title=${title}?color=${color}") diff --git a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetail.kt b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetail.kt index 5d81d73..048fcd9 100644 --- a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetail.kt +++ b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetail.kt @@ -10,12 +10,20 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.window.DialogProperties import androidx.fragment.app.viewModels +import androidx.navigation.NavType +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.dialog +import androidx.navigation.compose.rememberNavController import androidx.navigation.findNavController +import androidx.navigation.navArgument import com.dkin.chevit.core.mvi.MVIComposeFragment import com.dkin.chevit.presentation.deeplink.DeepLink import com.dkin.chevit.presentation.deeplink.deepLink import com.dkin.chevit.presentation.home.R +import com.dkin.chevit.presentation.home.contents.template.MoreBottomSheet import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -33,11 +41,51 @@ class TemplateDetail: return ComposeView(requireContext()).apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - TemplateDetailScreen( - modifier = Modifier.fillMaxSize(), - viewModel = viewModel, - onClickBack = { findNavController().popBackStack() } - ) + val navController = rememberNavController() + NavHost(navController = navController, startDestination = "detail") { + composable("detail") { + TemplateDetailScreen( + modifier = Modifier.fillMaxSize(), + viewModel = viewModel, + onClickBack = { findNavController().popBackStack() }, + openCategoryMoreSheet = { id, title, type -> + navController.navigate("categoryMore/${id}?title=${title}?type=${type.name}") + } + ) + } + dialog( + route = "categoryMore/{categoryId}?title={title}?type={type}", + arguments = listOf( + navArgument("categoryId") { type = NavType.StringType }, + navArgument("title") { type = NavType.StringType; defaultValue = "" }, + navArgument("type") { type = NavType.StringType; defaultValue = "" }, + ), + dialogProperties = DialogProperties(usePlatformDefaultWidth = false), + ) { + val categoryId = it.arguments?.getString("categoryId") ?: "" + val title = it.arguments?.getString("title") ?: "" + val type = it.arguments?.getString("type") ?: "" + MoreBottomSheet( + title = title, + navigateEditItem = { + navController.popBackStack() + deepLink( + DeepLink.EditCategory( + planId = planId, + categoryId = categoryId, + title = title, + type = type + ) + ) { popUpTo(R.id.templateDetail) } + }, + deleteItem = { + navController.popBackStack() + viewModel.deleteCategory(planId, categoryId) + }, + onClose = { navController.popBackStack() } + ) + } + } } } } diff --git a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailScreen.kt b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailScreen.kt index 3cce240..61ac0c4 100644 --- a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailScreen.kt +++ b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailScreen.kt @@ -1,8 +1,9 @@ package com.dkin.chevit.presentation.home.contents.template.detail +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -35,6 +36,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import com.dkin.chevit.presentation.common.model.CategoryType import com.dkin.chevit.presentation.resource.ChevitButtonFillMedium import com.dkin.chevit.presentation.resource.ChevitFloatingButton import com.dkin.chevit.presentation.resource.ChevitTheme @@ -50,7 +52,8 @@ import com.dkin.chevit.presentation.resource.util.clickableNoRipple fun TemplateDetailScreen( modifier: Modifier, viewModel: TemplateDetailViewModel, - onClickBack: () -> Unit + onClickBack: () -> Unit, + openCategoryMoreSheet: (id: String, title: String, type: CategoryType) -> Unit, ) { val state by viewModel.state.collectAsState() @@ -112,6 +115,7 @@ fun TemplateDetailScreen( CategoryListContents( categories = state.categories, onClickCategory = { id -> viewModel.onClickCategory(id) }, + onLongClickCategory = openCategoryMoreSheet ) Box( modifier = Modifier @@ -187,10 +191,12 @@ private fun CategoryEmptyContents( } } +@OptIn(ExperimentalFoundationApi::class) @Composable private fun CategoryListContents( categories: List, - onClickCategory: (categoryId: String) -> Unit + onClickCategory: (categoryId: String) -> Unit, + onLongClickCategory: (id: String, title: String, type: CategoryType) -> Unit, ) { Column( modifier = Modifier @@ -209,7 +215,16 @@ private fun CategoryListContents( modifier = Modifier .clip(RoundedCornerShape(8.dp)) .background(color = if (completed) ChevitTheme.colors.grey0 else ChevitTheme.colors.grey1) - .clickable { onClickCategory(category.categoryId) } + .combinedClickable( + onClick = { onClickCategory(category.categoryId) }, + onLongClick = { + onLongClickCategory( + category.categoryId, + category.title, + category.categoryType + ) + } + ) .padding(vertical = 12.dp, horizontal = 12.dp), horizontalAlignment = Alignment.CenterHorizontally ) { @@ -219,7 +234,10 @@ private fun CategoryListContents( .background(color = ChevitTheme.colors.white, shape = CircleShape), contentAlignment = Alignment.Center ) { - Image(painter = painterResource(id = category.categoryType.getCategoryIconResId()), contentDescription = "") + Image( + painter = painterResource(id = category.categoryType.getCategoryIconResId()), + contentDescription = "" + ) } Spacer(modifier = Modifier.height(6.dp)) Text( diff --git a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailViewModel.kt b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailViewModel.kt index f11e16c..b5ad511 100644 --- a/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailViewModel.kt +++ b/presentation/home/src/main/java/com/dkin/chevit/presentation/home/contents/template/detail/TemplateDetailViewModel.kt @@ -25,6 +25,10 @@ class TemplateDetailViewModel @Inject constructor() : setEffect { TemplateDetailEffect.NavigateToAddCategory } } + fun deleteCategory(planId: String, categoryId: String) { + //todo + } + fun onClickCategory(id: String) { setEffect { TemplateDetailEffect.NavigateToChecklistDetail(id) } }