-
Notifications
You must be signed in to change notification settings - Fork 0
feat(home): implement sorting functionality for coin list #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,14 +64,21 @@ internal fun HomeScreen(state: HomeUiState, onEvent: (HomeEvent) -> Unit, modifi | |
| } | ||
| } | ||
|
|
||
| // Sort Header (TODO: 정렬 기능 구현) | ||
| // Sort Header | ||
| val symbolSort = | ||
| if (state.sortField == SortField.Symbol) state.sortDirection else SortDirection.None | ||
| val priceSort = | ||
| if (state.sortField == SortField.Price) state.sortDirection else SortDirection.None | ||
| val changeSort = | ||
| if (state.sortField == SortField.Change) state.sortDirection else SortDirection.None | ||
|
|
||
| SortHeader( | ||
| symbolSort = SortDirection.None, | ||
| priceSort = SortDirection.Desc, | ||
| changeSort = SortDirection.None, | ||
| onSymbolClick = { /* TODO: 정렬 기능 구현 */ }, | ||
| onPriceClick = { /* TODO: 정렬 기능 구현 */ }, | ||
| onChangeClick = { /* TODO: 정렬 기능 구현 */ }, | ||
| symbolSort = symbolSort, | ||
| priceSort = priceSort, | ||
| changeSort = changeSort, | ||
| onSymbolClick = { onEvent(HomeEvent.OnSortClicked(SortField.Symbol)) }, | ||
| onPriceClick = { onEvent(HomeEvent.OnSortClicked(SortField.Price)) }, | ||
| onChangeClick = { onEvent(HomeEvent.OnSortClicked(SortField.Change)) }, | ||
|
Comment on lines
+79
to
+81
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 명시적으로 넣는거보다 |
||
| ) | ||
|
|
||
| // Coin List | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import io.soma.cryptobook.core.domain.navigation.AppPage | |
| import io.soma.cryptobook.core.domain.navigation.NavigationHelper | ||
| import io.soma.cryptobook.core.presentation.MviViewModel | ||
| import io.soma.cryptobook.home.domain.usecase.ObserveCoinListUseCase | ||
| import io.soma.cryptobook.home.presentation.component.sortheader.SortDirection | ||
| import javax.inject.Inject | ||
|
|
||
| @HiltViewModel | ||
|
|
@@ -31,6 +32,7 @@ class HomeViewModel @Inject constructor( | |
| is HomeEvent.OnCoinClicked -> navigationHelper.navigate( | ||
| AppPage.CoinDetail(event.symbol), | ||
| ) | ||
| is HomeEvent.OnSortClicked -> updateSort(event.field) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -39,11 +41,16 @@ class HomeViewModel @Inject constructor( | |
| observeCoinListUseCase().collect { result -> | ||
| when (result) { | ||
| is ObserveCoinListUseCase.Result.Success -> { | ||
| val sortedCoins = sortCoins( | ||
| coins = result.coinList.map { it.toCoinItem() }, | ||
| sortField = currentState.sortField, | ||
| sortDirection = currentState.sortDirection, | ||
| ) | ||
| reduce { | ||
| copy( | ||
| isLoading = false, | ||
| errorMsg = null, | ||
| coins = result.coinList.map { | ||
| coins = sortedCoins.coinList.map { | ||
| it.toCoinItem(coinImageResolver.getImageUrl(it.symbol)) | ||
| }, | ||
| ) | ||
|
|
@@ -63,4 +70,49 @@ class HomeViewModel @Inject constructor( | |
| } | ||
| } | ||
| } | ||
|
|
||
| private fun updateSort(field: SortField) { | ||
| val newDirection = if (field == currentState.sortField) { | ||
| toggleDirection(currentState.sortDirection) | ||
| } else { | ||
| defaultSortDirection(field) | ||
| } | ||
|
|
||
| reduce { | ||
| copy( | ||
| sortField = field, | ||
| sortDirection = newDirection, | ||
| coins = sortCoins(coins, field, newDirection), | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| private fun sortCoins( | ||
| coins: List<CoinItem>, | ||
| sortField: SortField, | ||
| sortDirection: SortDirection, | ||
| ): List<CoinItem> { | ||
| val comparator = when (sortField) { | ||
| SortField.Symbol -> compareBy<CoinItem> { it.symbol } | ||
| SortField.Price -> compareBy<CoinItem> { it.price } | ||
| SortField.Change -> compareBy<CoinItem> { it.priceChangePercentage24h } | ||
| } | ||
|
|
||
| return if (sortDirection == SortDirection.Desc) { | ||
| coins.sortedWith(comparator).asReversed() | ||
| }else{ | ||
| coins.sortedWith(comparator) | ||
|
Comment on lines
+101
to
+104
|
||
| } | ||
| } | ||
|
|
||
| private fun toggleDirection(current: SortDirection): SortDirection { | ||
| return if (current == SortDirection.Asc) SortDirection.Desc else SortDirection.Asc | ||
| } | ||
|
|
||
| private fun defaultSortDirection(field: SortField): SortDirection { | ||
| return when (field) { | ||
| SortField.Symbol -> SortDirection.Asc | ||
| SortField.Price, SortField.Change -> SortDirection.Desc | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,7 +80,7 @@ fun SortHeaderItem( | |
| text = label, | ||
| fontFamily = fontFamily, | ||
| fontWeight = FontWeight.Bold, | ||
| fontSize = 14.sp, | ||
| fontSize = 12.sp, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lineHeight = 20.sp 이기 때문에 fontSize를 바꾸는 것은 의미가 없습니다. 바꾼 이유가 있을까요?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 24h change % 부분이 가로로 길이가 초과되서요 |
||
| lineHeight = 20.sp, | ||
| color = textColor, | ||
| ) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HomeUiStatenow exposessortDirectionusingSortDirectionfrom thecomponent.sortheaderpackage, which couples the screen contract to a specific UI component implementation. In other screens (e.g.coin-detail/presentation/src/main/java/io/soma/cryptobook/coindetail/presentation/CoinDetailContract.kt), UI state types stay independent of leaf UI components, so it would be more consistent and maintainable to defineSortDirectionalongsideHomeUiState(or in a shared presentation package) and letSortHeader/SortHeaderItemdepend on that instead.