fix: add search to category picker

This commit is contained in:
Rafal Wisniewski
2026-05-06 10:49:09 +02:00
parent 79551ab69d
commit 6c067f64ce
5 changed files with 116 additions and 37 deletions

View File

@@ -98,7 +98,8 @@ fun AddExpenseBottomSheet(
expenseDtoToEdit = expenseDtoToEdit,
state = state,
currentTrip = currentTrip ?: Trip.DUMMY,
categories = categories
categories = categories,
onSaveCategory = {expenseAndCategoryViewModel.save(it)}
)
}
@@ -111,7 +112,8 @@ fun AddExpenseBottomSheet(
expenseDtoToEdit: ExpenseDto?,
state: SheetState,
currentTrip: Trip,
categories: List<Category>
categories: List<Category>,
onSaveCategory: (Category) -> Unit
) {
val currentTripId = currentTrip.id
@@ -319,7 +321,8 @@ fun AddExpenseBottomSheet(
category = selectedCategory
},
selected = category,
categories = categories
categories = categories,
onSaveCategory = onSaveCategory
)
}
}
@@ -578,7 +581,8 @@ fun PreviewAddExpenseDisabled() {
LocalDate.parse("2020-01-15"),
Currencies.entries.random().name
),
categories = categoriesToPreview
categories = categoriesToPreview,
{}
)
}
@@ -622,7 +626,8 @@ fun PreviewAddExpenseEnabled() {
LocalDate.parse("2020-01-11"),
Currencies.entries.random().name
),
categories = categoriesToPreview
categories = categoriesToPreview,
{}
)
}

View File

@@ -13,22 +13,26 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
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.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.graphics.toColorInt
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import cc.n0th1ng.tripmoney.R.string
import cc.n0th1ng.tripmoney.data.entity.Category
import cc.n0th1ng.tripmoney.screens.AddCategoryDialog
import cc.n0th1ng.tripmoney.viewmodel.ExpenseAndCategoryViewModel
import cc.n0th1ng.tripmoney.screens.addexpense.categoriesToPreview
import cc.n0th1ng.tripmoney.theme.TripMoneyTheme
import cc.n0th1ng.tripmoney.utils.AllPreviews
import cc.n0th1ng.tripmoney.utils.SearchTextOutlined
import com.composables.icons.materialsymbols.outlined.R
@Composable
@@ -37,22 +41,41 @@ fun CategorySelectionDialog(
onCategorySelected: (Category) -> Unit,
selected: Category?,
categories: List<Category>,
onSaveCategory: (Category) -> Unit
) {
val expenseAndCategoryViewModel: ExpenseAndCategoryViewModel = hiltViewModel()
val listState = rememberLazyListState()
var showAddCategoryDialog by remember { mutableStateOf(false) }
AlertDialog(
onDismissRequest = onDismiss, title = { Text(stringResource(string.pick_category)) }, text = {
onDismissRequest = onDismiss,
title = { Text(stringResource(string.pick_category)) },
text = {
val focusRequester = remember { FocusRequester() }
LaunchedEffect(Unit) {
if(selected != null) {
listState.animateScrollToItem(categories.indexOfFirst { it == selected })
}
// focusRequester.requestFocus()
}
Column {
var search by remember { mutableStateOf("") }
val filteredCategories = if (search.isBlank()) {
categories
} else {
categories.filter { category ->
category.name.lowercase().contains(search.lowercase())
}
}
LazyColumn(
modifier = Modifier.heightIn(max = 300.dp),
state = listState,
horizontalAlignment = Alignment.CenterHorizontally,
) {
items(
count = categories.size,
key = { index -> categories[index].id }) { index ->
val category = categories[index]
count = filteredCategories.size,
key = { index -> filteredCategories[index].id }) { index ->
val category = filteredCategories[index]
Row(
modifier = Modifier
.fillMaxWidth()
@@ -83,24 +106,41 @@ fun CategorySelectionDialog(
.clickable {
showAddCategoryDialog = true
}
.padding(top = 15.dp),
.padding(bottom = 10.dp),
verticalAlignment = Alignment.CenterVertically) {
Icon(
painter = painterResource(R.drawable.materialsymbols_ic_add_outlined),
contentDescription = stringResource(string.category)
)
Text(
text = stringResource(string.add_new), modifier = Modifier.padding(start = 8.dp),
text = stringResource(string.add_new),
modifier = Modifier.padding(start = 8.dp),
)
}
SearchTextOutlined(
text = search,
onTextChange = { newText -> search = newText },
focusRequester = focusRequester
)
}
}, confirmButton = {})
},
confirmButton = {})
if (showAddCategoryDialog) {
AddCategoryDialog(onDismiss = {
showAddCategoryDialog = false
}, onSave = { category ->
expenseAndCategoryViewModel.save(category)
onSaveCategory(category)
showAddCategoryDialog = false
})
}
}
@AllPreviews
@Composable
fun PreviewCategorySelectionDialog() {
TripMoneyTheme {
CategorySelectionDialog(
{}, {},
categoriesToPreview.random(), categoriesToPreview, {})
}
}

View File

@@ -12,9 +12,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -25,14 +23,13 @@ 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.res.stringResource
import androidx.compose.ui.unit.dp
import cc.n0th1ng.tripmoney.R
import cc.n0th1ng.tripmoney.theme.TripMoneyTheme
import cc.n0th1ng.tripmoney.utils.AllPreviews
import cc.n0th1ng.tripmoney.utils.Currencies
import com.composables.icons.materialsymbols.outlined.R.drawable
import cc.n0th1ng.tripmoney.utils.SearchTextOutlined
@Composable
fun CurrencySelectionDialog(
@@ -57,20 +54,6 @@ fun CurrencySelectionDialog(
}
Column(verticalArrangement = Arrangement.spacedBy(5.dp)) {
OutlinedTextField(
value = search,
onValueChange = { newText ->
search = newText
},
modifier = Modifier.fillMaxWidth(),
trailingIcon = {
Icon(
painter = painterResource(drawable.materialsymbols_ic_search_outlined),
contentDescription = "search"
)
}
)
val filteredCurrencies = if (search.isBlank()) {
currencies
} else {
@@ -79,7 +62,12 @@ fun CurrencySelectionDialog(
}
}
LazyColumn(state = scrollState) {
LazyColumn(
state = scrollState,
modifier = Modifier
.weight(1f)
.padding(bottom = 10.dp)
) {
items(
count = filteredCurrencies.size,
key = { index -> filteredCurrencies[index] }
@@ -104,6 +92,8 @@ fun CurrencySelectionDialog(
}
}
}
SearchTextOutlined(
text = search, onTextChange = { newText -> search = newText })
}
},
confirmButton = {},