Skip to content

Commit

Permalink
feat: 필터 UI 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
rhkrwngud445 committed Sep 29, 2024
1 parent 34e7fa1 commit 88d1487
Show file tree
Hide file tree
Showing 13 changed files with 480 additions and 355 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.withpeace.withpeace.feature.policylist.uistate
package com.withpeace.withpeace.core.ui.policy.filtersetting

import com.withpeace.withpeace.core.domain.model.policy.PolicyFilters
import com.withpeace.withpeace.core.ui.policy.ClassificationUiModel
Expand Down
12 changes: 12 additions & 0 deletions core/ui/src/main/res/drawable/ic_filter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M21.25,12H8.895M4.534,12H2.75M4.534,12C4.534,11.422 4.764,10.867 5.173,10.458C5.581,10.05 6.136,9.82 6.714,9.82C7.292,9.82 7.847,10.05 8.255,10.458C8.664,10.867 8.894,11.422 8.894,12C8.894,12.578 8.664,13.133 8.255,13.542C7.847,13.95 7.292,14.18 6.714,14.18C6.136,14.18 5.581,13.95 5.173,13.542C4.764,13.133 4.534,12.578 4.534,12ZM21.25,18.607H15.502M15.502,18.607C15.502,19.185 15.272,19.74 14.863,20.149C14.454,20.558 13.899,20.788 13.321,20.788C12.743,20.788 12.188,20.557 11.78,20.149C11.371,19.74 11.141,19.185 11.141,18.607M15.502,18.607C15.502,18.029 15.272,17.475 14.863,17.066C14.454,16.657 13.899,16.427 13.321,16.427C12.743,16.427 12.188,16.657 11.78,17.066C11.371,17.474 11.141,18.029 11.141,18.607M11.141,18.607H2.75M21.25,5.393H18.145M13.784,5.393H2.75M13.784,5.393C13.784,4.815 14.014,4.26 14.422,3.852C14.831,3.443 15.386,3.213 15.964,3.213C16.25,3.213 16.534,3.269 16.798,3.379C17.063,3.489 17.303,3.649 17.506,3.852C17.708,4.054 17.868,4.294 17.978,4.559C18.088,4.823 18.144,5.107 18.144,5.393C18.144,5.679 18.088,5.963 17.978,6.227C17.868,6.492 17.708,6.732 17.506,6.935C17.303,7.137 17.063,7.298 16.798,7.407C16.534,7.517 16.25,7.573 15.964,7.573C15.386,7.573 14.831,7.343 14.422,6.935C14.014,6.526 13.784,5.971 13.784,5.393Z"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="#9A70E2"
android:strokeLineCap="round"/>
</vector>
9 changes: 9 additions & 0 deletions core/ui/src/main/res/drawable/ic_filter_close.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6.292,6.318C6.479,6.131 6.733,6.027 6.997,6.027C7.261,6.027 7.515,6.131 7.702,6.318L11.987,10.593L16.271,6.318C16.393,6.187 16.548,6.091 16.72,6.04C16.892,5.99 17.075,5.987 17.248,6.031C17.422,6.075 17.58,6.166 17.707,6.292C17.834,6.419 17.924,6.577 17.968,6.751C18.012,6.924 18.009,7.106 17.959,7.277C17.908,7.449 17.813,7.603 17.681,7.725L13.397,12.001L17.681,16.276C17.813,16.398 17.909,16.552 17.959,16.724C18.01,16.896 18.013,17.078 17.969,17.251C17.924,17.424 17.834,17.583 17.707,17.709C17.58,17.835 17.422,17.925 17.248,17.969C17.074,18.013 16.892,18.01 16.72,17.96C16.548,17.91 16.393,17.814 16.271,17.683L11.987,13.408L7.702,17.683C7.513,17.859 7.263,17.955 7.004,17.951C6.746,17.946 6.499,17.842 6.316,17.66C6.133,17.477 6.029,17.231 6.024,16.973C6.02,16.715 6.116,16.465 6.292,16.276L10.576,12.001L6.292,7.725C6.105,7.538 6,7.285 6,7.022C6,6.758 6.105,6.505 6.292,6.318Z"
android:fillColor="#000000"/>
</vector>
9 changes: 9 additions & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,13 @@
<string name="classification_wefare_and_culture">복지,문화</string>
<string name="classification_partification_and_right">참여,권리</string>
<string name="classification_etc">기타</string>

<!-- Policy Filter -->
<string name="filter">필터</string>
<string name="filter_close">필터 닫기</string>
<string name="filter_expanded">더보기</string>
<string name="policy_classification_image">정책 분류 이미지</string>
<string name="region">지역</string>
<string name="filter_all_off">전체 해제</string>
<string name="search">검색하기</string>
</resources>
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.withpeace.withpeace.feature.home

import androidx.compose.foundation.Image
import androidx.compose.foundation.MutatePriority
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.stopScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -19,13 +21,21 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -35,27 +45,49 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.skydoves.balloon.BalloonAnimation
import com.skydoves.balloon.BalloonSizeSpec
import com.skydoves.balloon.compose.Balloon
import com.skydoves.balloon.compose.rememberBalloonBuilder
import com.skydoves.balloon.compose.setBackgroundColor
import com.withpeace.withpeace.core.designsystem.theme.WithpeaceTheme
import com.withpeace.withpeace.core.ui.analytics.TrackScreenViewEvent
import com.withpeace.withpeace.core.ui.policy.ClassificationUiModel
import com.withpeace.withpeace.core.ui.policy.RegionUiModel
import com.withpeace.withpeace.core.ui.policy.filtersetting.FilterBottomSheet
import com.withpeace.withpeace.core.ui.policy.filtersetting.PolicyFiltersUiModel
import kotlinx.coroutines.launch

@Composable
fun HomeRoute(
onShowSnackBar: (message: String) -> Unit = {},
onNavigationSnackBar: (message: String) -> Unit = {},
viewModel: HomeViewModel = hiltViewModel(),
onNavigationSnackBar: (message: String) -> Unit = {},
onPolicyClick: (String) -> Unit,
) {
HomeScreen()
val selectedFilterUiState = viewModel.selectingFilters.collectAsStateWithLifecycle()
HomeScreen(
selectedFilterUiState = selectedFilterUiState.value,
onClassificationCheckChanged = viewModel::onCheckClassification,
onRegionCheckChanged = viewModel::onCheckRegion,
onFilterAllOff = viewModel::onFilterAllOff,
onSearchWithFilter = viewModel::onCompleteFilter,
onCloseFilter = viewModel::onCancelFilter,
onDismissRequest = viewModel::onCancelFilter,
)
}

@Composable
fun HomeScreen(
modifier: Modifier = Modifier,
selectedFilterUiState: PolicyFiltersUiModel,
onDismissRequest: () -> Unit,
onClassificationCheckChanged: (ClassificationUiModel) -> Unit,
onRegionCheckChanged: (RegionUiModel) -> Unit,
onFilterAllOff: () -> Unit,
onSearchWithFilter: () -> Unit,
onCloseFilter: () -> Unit,
) {
Column(modifier = modifier.fillMaxSize()) {
HomeHeader(
Expand All @@ -65,16 +97,32 @@ fun HomeScreen(
modifier = modifier.height(1.dp),
color = WithpeaceTheme.colors.SystemGray3,
)

ScrollSection(modifier)
ScrollSection(
selectedFilterUiState = selectedFilterUiState,
onDismissRequest = onDismissRequest,
onClassificationCheckChanged = onClassificationCheckChanged,
onRegionCheckChanged = onRegionCheckChanged,
onFilterAllOff = onFilterAllOff,
onSearchWithFilter = onSearchWithFilter,
onCloseFilter = onCloseFilter,
)

}
TrackScreenViewEvent(screenName = "home")
}

@OptIn(ExperimentalLayoutApi::class)
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
private fun ScrollSection(modifier: Modifier) {
private fun ScrollSection(
modifier: Modifier = Modifier,
selectedFilterUiState: PolicyFiltersUiModel,
onDismissRequest: () -> Unit,
onClassificationCheckChanged: (ClassificationUiModel) -> Unit,
onRegionCheckChanged: (RegionUiModel) -> Unit,
onFilterAllOff: () -> Unit,
onSearchWithFilter: () -> Unit,
onCloseFilter: () -> Unit,
) {
val builder = rememberBalloonBuilder {
setIsVisibleArrow(false)
setWidth(BalloonSizeSpec.WRAP)
Expand All @@ -85,7 +133,52 @@ private fun ScrollSection(modifier: Modifier) {
setBalloonAnimation(BalloonAnimation.FADE)
setArrowSize(0)
}
var showBottomSheet by remember { mutableStateOf(false) }
val bottomSheetChildScrollState = rememberScrollState()

val sheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true,
)
val scope = rememberCoroutineScope()

LaunchedEffect(bottomSheetChildScrollState.canScrollBackward) {
if (bottomSheetChildScrollState.value == 0) {
bottomSheetChildScrollState.stopScroll(MutatePriority.PreventUserInput)
}
}

if (showBottomSheet) {
ModalBottomSheet(
modifier = modifier,
dragHandle = null,
onDismissRequest = {
onDismissRequest()
showBottomSheet = false
},
sheetState = sheetState,
) {
FilterBottomSheet(
modifier = modifier,
scrollState = bottomSheetChildScrollState,
selectedFilterUiState = selectedFilterUiState,
onClassificationCheckChanged = onClassificationCheckChanged,
onRegionCheckChanged = onRegionCheckChanged,
onFilterAllOff = onFilterAllOff,
onSearchWithFilter = {
scope.launch { sheetState.hide() }.invokeOnCompletion {
showBottomSheet = false
onSearchWithFilter()
}
},
onCloseFilter = {
scope.launch { sheetState.hide() }.invokeOnCompletion {
showBottomSheet = false
onCloseFilter()
}
},
)
}
}

LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
Expand Down Expand Up @@ -136,7 +229,10 @@ private fun ScrollSection(modifier: Modifier) {
shape = CircleShape,
)
.padding(4.dp)
.size(16.dp),
.size(16.dp)
.clickable {
showBottomSheet = true
},
contentDescription = "",
)
List(5) { //TODO("데이터 변경")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,63 @@
package com.withpeace.withpeace.feature.home

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.withpeace.withpeace.core.domain.model.policy.PolicyFilters
import com.withpeace.withpeace.core.ui.policy.ClassificationUiModel
import com.withpeace.withpeace.core.ui.policy.RegionUiModel
import com.withpeace.withpeace.core.ui.policy.filtersetting.PolicyFiltersUiModel
import com.withpeace.withpeace.core.ui.policy.filtersetting.toDomain
import com.withpeace.withpeace.core.ui.policy.filtersetting.toUiModel
import com.withpeace.withpeace.core.ui.policy.toDomain
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
) : ViewModel() {
private val _selectingFilters = MutableStateFlow(PolicyFilters())
val selectingFilters: StateFlow<PolicyFiltersUiModel> =
_selectingFilters.map { it.toUiModel() }.stateIn(
scope = viewModelScope,
SharingStarted.WhileSubscribed(),
PolicyFiltersUiModel(),
)

private var completedFilters = PolicyFilters()

init {
}

fun onCheckClassification(classification: ClassificationUiModel) {
_selectingFilters.update {
it.updateClassification(classification.toDomain())
}
}

fun onCheckRegion(region: RegionUiModel) {
_selectingFilters.update {
it.updateRegion(region.toDomain())
}
}

fun onCompleteFilter() {
completedFilters = selectingFilters.value.toDomain()
// api
}

fun onCancelFilter() {
_selectingFilters.update { completedFilters }
}

fun onFilterAllOff() {
_selectingFilters.update {
it.removeAll()
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ import com.withpeace.withpeace.core.ui.analytics.TrackScreenViewEvent
import com.withpeace.withpeace.core.ui.bookmark.BookmarkButton
import com.withpeace.withpeace.core.ui.policy.ClassificationUiModel
import com.withpeace.withpeace.core.ui.policy.RegionUiModel
import com.withpeace.withpeace.feature.policylist.filtersetting.FilterBottomSheet
import com.withpeace.withpeace.core.ui.policy.filtersetting.FilterBottomSheet
import com.withpeace.withpeace.feature.policylist.uistate.PolicyListUiEvent
import com.withpeace.withpeace.feature.policylist.uistate.PolicyFiltersUiModel
import com.withpeace.withpeace.core.ui.policy.filtersetting.PolicyFiltersUiModel
import com.withpeace.withpeace.feature.policylist.uistate.YouthPolicyUiModel
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -457,7 +457,6 @@ private fun YouthPolicyCard(
style = WithpeaceTheme.typography.Tag,
)


Image(
modifier = modifier
.size(57.dp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import com.withpeace.withpeace.core.domain.usecase.GetYouthPoliciesUseCase
import com.withpeace.withpeace.core.ui.policy.ClassificationUiModel
import com.withpeace.withpeace.core.ui.policy.RegionUiModel
import com.withpeace.withpeace.core.ui.policy.toDomain
import com.withpeace.withpeace.core.ui.policy.filtersetting.PolicyFiltersUiModel
import com.withpeace.withpeace.core.ui.policy.filtersetting.toDomain
import com.withpeace.withpeace.core.ui.policy.filtersetting.toUiModel
import com.withpeace.withpeace.feature.policylist.uistate.PolicyListUiEvent
import com.withpeace.withpeace.feature.policylist.uistate.PolicyFiltersUiModel
import com.withpeace.withpeace.feature.policylist.uistate.YouthPolicyUiModel
import com.withpeace.withpeace.feature.policylist.uistate.toDomain
import com.withpeace.withpeace.feature.policylist.uistate.toUiModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
Expand Down
Loading

0 comments on commit 88d1487

Please sign in to comment.