diff --git a/app/src/main/java/cc/n0th1ng/tripmoney/data/dao/CategoryDao.kt b/app/src/main/java/cc/n0th1ng/tripmoney/data/dao/CategoryDao.kt index a8057f4..613c883 100644 --- a/app/src/main/java/cc/n0th1ng/tripmoney/data/dao/CategoryDao.kt +++ b/app/src/main/java/cc/n0th1ng/tripmoney/data/dao/CategoryDao.kt @@ -2,7 +2,6 @@ package cc.n0th1ng.tripmoney.data.dao import androidx.room.Dao import androidx.room.Delete -import androidx.room.Insert import androidx.room.Query import androidx.room.Transaction import androidx.room.Upsert @@ -21,7 +20,7 @@ interface CategoryDao { @Transaction @Query( """ - SELECT * FROM category WHERE archived is 0 + SELECT * FROM category WHERE archived is 0 ORDER BY name """ ) fun categories(): Flow> diff --git a/app/src/main/java/cc/n0th1ng/tripmoney/screens/addexpense/AddExpenseBottomSheet.kt b/app/src/main/java/cc/n0th1ng/tripmoney/screens/addexpense/AddExpenseBottomSheet.kt index 54b371c..2a0b768 100644 --- a/app/src/main/java/cc/n0th1ng/tripmoney/screens/addexpense/AddExpenseBottomSheet.kt +++ b/app/src/main/java/cc/n0th1ng/tripmoney/screens/addexpense/AddExpenseBottomSheet.kt @@ -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 + categories: List, + 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, + {} ) } diff --git a/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CategorySelectionDialog.kt b/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CategorySelectionDialog.kt index 1aae1db..d6ae562 100644 --- a/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CategorySelectionDialog.kt +++ b/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CategorySelectionDialog.kt @@ -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, + 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, {}) + } } \ No newline at end of file diff --git a/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CurrencySelectionDialog.kt b/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CurrencySelectionDialog.kt index b5014db..994ea59 100644 --- a/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CurrencySelectionDialog.kt +++ b/app/src/main/java/cc/n0th1ng/tripmoney/screens/listexpense/CurrencySelectionDialog.kt @@ -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 = {}, diff --git a/app/src/main/java/cc/n0th1ng/tripmoney/utils/SearchTextOutlined.kt b/app/src/main/java/cc/n0th1ng/tripmoney/utils/SearchTextOutlined.kt new file mode 100644 index 0000000..d7d16e3 --- /dev/null +++ b/app/src/main/java/cc/n0th1ng/tripmoney/utils/SearchTextOutlined.kt @@ -0,0 +1,45 @@ +package cc.n0th1ng.tripmoney.utils + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedTextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.res.painterResource +import com.composables.icons.materialsymbols.outlined.R.drawable + +@Composable +fun SearchTextOutlined( + modifier: Modifier = Modifier, + text: String, + onTextChange: (String) -> Unit, + focusRequester: FocusRequester = FocusRequester() +) { + OutlinedTextField( + value = text, + onValueChange = onTextChange, + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester), + trailingIcon = { + if (text.isNotBlank()) { + Icon( + imageVector = Icons.Default.Close, + contentDescription = "close", + modifier = Modifier.clickable(true, onClick = { onTextChange("") }) + ) + } else { + Icon( + painter = painterResource(drawable.materialsymbols_ic_search_outlined), + contentDescription = "search" + ) + } + + } + ) +} \ No newline at end of file