diff --git a/screen/categories/src/main/java/com/ivy/categories/CategoriesScreen.kt b/screen/categories/src/main/java/com/ivy/categories/CategoriesScreen.kt index e55719c897..74d91b50e8 100644 --- a/screen/categories/src/main/java/com/ivy/categories/CategoriesScreen.kt +++ b/screen/categories/src/main/java/com/ivy/categories/CategoriesScreen.kt @@ -165,7 +165,7 @@ private fun BoxWithConstraintsScope.UI( if (state.showCategorySearchBar) { Spacer(Modifier.height(16.dp)) - SearchField(onSearch = {}) + SearchField(onSearch = { onEvent(CategoriesScreenEvent.OnSearchQueryUpdate(it)) }) } Spacer(Modifier.height(16.dp)) } @@ -797,6 +797,16 @@ fun CategoriesScreenUiTest(isDark: Boolean) { Preview(theme) } +/** For screenshot testing */ +@Composable +fun CategoriesScreenWithSearchBarUiTest(isDark: Boolean) { + val theme = when (isDark) { + true -> Theme.DARK + false -> Theme.LIGHT + } + Preview(theme = theme, displaySearchBarEnabled = true) +} + /** For screenshot testing */ @Composable fun CategoriesScreenCompactUiTest(isDark: Boolean) { @@ -805,4 +815,14 @@ fun CategoriesScreenCompactUiTest(isDark: Boolean) { false -> Theme.LIGHT } Preview(theme, compactModeEnabled = true) +} + +/** For screenshot testing */ +@Composable +fun CategoriesScreenWithSearchBarCompactUiTest(isDark: Boolean) { + val theme = when (isDark) { + true -> Theme.DARK + false -> Theme.LIGHT + } + Preview(theme, compactModeEnabled = true, displaySearchBarEnabled = true) } \ No newline at end of file diff --git a/screen/categories/src/main/java/com/ivy/categories/CategoriesScreenEvent.kt b/screen/categories/src/main/java/com/ivy/categories/CategoriesScreenEvent.kt index b6e538c139..527995dbf4 100644 --- a/screen/categories/src/main/java/com/ivy/categories/CategoriesScreenEvent.kt +++ b/screen/categories/src/main/java/com/ivy/categories/CategoriesScreenEvent.kt @@ -17,4 +17,5 @@ sealed interface CategoriesScreenEvent { data class OnSortOrderModalVisible(val visible: Boolean) : CategoriesScreenEvent data class OnCategoryModalVisible(val categoryModalData: CategoryModalData?) : CategoriesScreenEvent + data class OnSearchQueryUpdate(val queryString: String) : CategoriesScreenEvent } diff --git a/screen/categories/src/main/java/com/ivy/categories/CategoriesViewModel.kt b/screen/categories/src/main/java/com/ivy/categories/CategoriesViewModel.kt index 56cc92f2c8..55f94fc852 100644 --- a/screen/categories/src/main/java/com/ivy/categories/CategoriesViewModel.kt +++ b/screen/categories/src/main/java/com/ivy/categories/CategoriesViewModel.kt @@ -9,7 +9,6 @@ import com.ivy.base.legacy.SharedPrefs import com.ivy.base.legacy.Transaction import com.ivy.base.time.TimeConverter import com.ivy.base.time.TimeProvider -import com.ivy.ui.ComposeViewModel import com.ivy.data.repository.CategoryRepository import com.ivy.domain.features.Features import com.ivy.frp.action.thenMap @@ -17,6 +16,7 @@ import com.ivy.frp.thenInvokeAfter import com.ivy.legacy.data.model.TimePeriod import com.ivy.legacy.datamodel.Account import com.ivy.legacy.utils.ioThread +import com.ivy.ui.ComposeViewModel import com.ivy.wallet.domain.action.account.AccountsAct import com.ivy.wallet.domain.action.category.LegacyCategoryIncomeWithAccountFiltersAct import com.ivy.wallet.domain.action.settings.BaseCurrencyAct @@ -55,6 +55,8 @@ class CategoriesViewModel @Inject constructor( private val baseCurrency = mutableStateOf("") private val categories = mutableStateOf>(persistentListOf()) + private val allCategories = + mutableStateOf>(persistentListOf()) private val reorderModalVisible = mutableStateOf(false) private val categoryModalData = mutableStateOf(null) private val sortModalVisible = mutableStateOf(false) @@ -78,6 +80,7 @@ class CategoriesViewModel @Inject constructor( ) } + @Composable private fun getCompactCategoriesMode(): Boolean { return features.compactCategoriesMode.asEnabledState() @@ -132,7 +135,11 @@ class CategoriesViewModel @Inject constructor( ioThread { val range = TimePeriod.currentMonth( startDayOfMonth = ivyContext.startDayOfMonth - ).toRange(ivyContext.startDayOfMonth, timeConverter, timeProvider) // this must be monthly + ).toRange( + ivyContext.startDayOfMonth, + timeConverter, + timeProvider + ) // this must be monthly allAccounts = accountsAct(Unit) baseCurrency.value = baseCurrencyAct(Unit) @@ -141,7 +148,7 @@ class CategoriesViewModel @Inject constructor( TrnsWithRangeAndAccFiltersAct.Input( range = range, accountIdFilterSet = suspend { allAccounts } thenMap { it.id } - thenInvokeAfter { it.toHashSet() } + thenInvokeAfter { it.toHashSet() } ) ) @@ -177,9 +184,23 @@ class CategoriesViewModel @Inject constructor( } val sortedList = sortList(categories, sortOrder.value).toImmutableList() + this.allCategories.value = sortedList + this.categories.value = this.allCategories.value + + } + } - this.categories.value = sortedList + private fun filterCategories(queryString: String) { + var unsortedList : List + if (queryString.isNotEmpty()) { + unsortedList = this.allCategories.value.filter { + it.category.name.value.toLowerCase().contains(queryString.toLowerCase().trim()) + } + + } else { + unsortedList = this.allCategories.value } + this.categories.value = sortList(unsortedList, sortOrder.value).toImmutableList() } private suspend fun reorder( @@ -250,6 +271,8 @@ class CategoriesViewModel @Inject constructor( is CategoriesScreenEvent.OnCategoryModalVisible -> { categoryModalData.value = event.categoryModalData } + + is CategoriesScreenEvent.OnSearchQueryUpdate -> filterCategories(event.queryString) } } } diff --git a/screen/categories/src/test/java/com/ivy/categories/CategoriesScreenPaparazziTest.kt b/screen/categories/src/test/java/com/ivy/categories/CategoriesScreenPaparazziTest.kt index 1a8e1297a5..99396e9263 100644 --- a/screen/categories/src/test/java/com/ivy/categories/CategoriesScreenPaparazziTest.kt +++ b/screen/categories/src/test/java/com/ivy/categories/CategoriesScreenPaparazziTest.kt @@ -19,10 +19,24 @@ class CategoriesScreenPaparazziTest( } } + @Test + fun `snapshot Categories nonCompact Screen with search bar`() { + snapshot(theme) { + CategoriesScreenWithSearchBarUiTest(theme == PaparazziTheme.Dark) + } + } + @Test fun `snapshot Categories compact Screen`() { snapshot(theme) { CategoriesScreenCompactUiTest(theme == PaparazziTheme.Dark) } } + + @Test + fun `snapshot Categories compact Screen with search bar`() { + snapshot(theme) { + CategoriesScreenWithSearchBarCompactUiTest(theme == PaparazziTheme.Dark) + } + } } \ No newline at end of file