Merge remote-tracking branch 'origin/Florian'

# Conflicts:
#	Ledger/app/src/main/java/at/xaxa/ledger/ui/AppViewModelProvider.kt
#	Ledger/app/src/main/java/at/xaxa/ledger/ui/category/edit/EditCategory.kt
This commit is contained in:
Xaver 2025-01-15 20:57:02 +01:00
commit 8b57b46546
6 changed files with 160 additions and 92 deletions

View File

@ -43,9 +43,15 @@ class EntryRepository(private val ledgerDao: LedgerDao){
suspend fun updateEntry(entry: Entry) { suspend fun updateEntry(entry: Entry) {
ledgerDao.updateEntry(EntryEntity(entry.id, entry.name, entry.amount, entry.date, entry.categoryID)) ledgerDao.updateEntry(EntryEntity(entry.id, entry.name, entry.amount, entry.date, entry.categoryID))
} }
suspend fun updateCategory(category: CategoryEntity) {
ledgerDao.updateCategory(CategoryEntity(category._id, category.categoryName, category.icon))
}
suspend fun deleteEntry(entry: Entry) { suspend fun deleteEntry(entry: Entry) {
ledgerDao.deleteEntry(EntryEntity(_id = entry.id, entry.name, entry.amount, entry.date, entry.categoryID)) ledgerDao.deleteEntry(EntryEntity(_id = entry.id, entry.name, entry.amount, entry.date, entry.categoryID))
} }
suspend fun deleteCategory(category: CategoryEntity) {
ledgerDao.deleteCategory(CategoryEntity(_id = category._id, category.categoryName, category.icon))
}
} }

View File

@ -7,7 +7,8 @@ import androidx.lifecycle.viewmodel.viewModelFactory
import at.xaxa.ledger.LedgerApplication import at.xaxa.ledger.LedgerApplication
import at.xaxa.ledger.ui.entry.add.AddViewModel import at.xaxa.ledger.ui.entry.add.AddViewModel
import at.xaxa.ledger.ui.category.CategoryViewModel import at.xaxa.ledger.ui.category.CategoryViewModel
import at.xaxa.ledger.ui.entry.edit.EditViewModel import at.xaxa.ledger.ui.category.edit.EditCategoryViewModel
import at.xaxa.ledger.ui.edit.EditViewModel
import at.xaxa.ledger.ui.home.HomeViewModel import at.xaxa.ledger.ui.home.HomeViewModel
@ -27,5 +28,8 @@ object AppViewModelProvider {
initializer { initializer {
CategoryViewModel(this.createSavedStateHandle(), (this[APPLICATION_KEY] as LedgerApplication).entryRepository) CategoryViewModel(this.createSavedStateHandle(), (this[APPLICATION_KEY] as LedgerApplication).entryRepository)
} }
initializer {
EditCategoryViewModel(this.createSavedStateHandle(), (this[APPLICATION_KEY] as LedgerApplication).entryRepository)
}
} }
} }

View File

@ -81,7 +81,7 @@ fun LedgerApp(modifier: Modifier = Modifier){
backStackEntry -> backStackEntry ->
EditCategory( EditCategory(
modifier = Modifier, modifier = Modifier,
onCardClick = { onButtonClick = {
navController.navigate("category") navController.navigate("category")
} }
) )
@ -89,7 +89,7 @@ fun LedgerApp(modifier: Modifier = Modifier){
composable(AppRoutes.AddCategory.route){ composable(AppRoutes.AddCategory.route){
AddCategory( AddCategory(
onButtonClick = { onButtonClick = {
navController.navigate("gome") navController.navigate("home")
} }
) )
} }

View File

@ -1,6 +1,7 @@
package at.xaxa.ledger.ui.category.edit package at.xaxa.ledger.ui.category.edit
import android.util.Log import android.util.Log
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -8,7 +9,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.ExposedDropdownMenuDefaults.TrailingIcon import androidx.compose.material3.ExposedDropdownMenuDefaults.TrailingIcon
import androidx.compose.material3.Icon
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -22,110 +25,116 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import at.xaxa.ledger.data.Entry import at.xaxa.ledger.data.Entry
import at.xaxa.ledger.data.db.Category.CategoryEntity
import at.xaxa.ledger.ui.AppViewModelProvider import at.xaxa.ledger.ui.AppViewModelProvider
import at.xaxa.ledger.ui.ButtonDanger import at.xaxa.ledger.ui.ButtonDanger
import at.xaxa.ledger.ui.ButtonSuccess import at.xaxa.ledger.ui.ButtonSuccess
import at.xaxa.ledger.ui.DatePickerDocked import at.xaxa.ledger.ui.DatePickerDocked
import at.xaxa.ledger.ui.entry.edit.EditViewModel import at.xaxa.ledger.ui.category.CategoryViewModel
import at.xaxa.ledger.ui.category.iconNames
import at.xaxa.ledger.ui.category.icons
import at.xaxa.ledger.ui.edit.EditViewModel
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun EditCategory(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel : EditViewModel = viewModel(factory = AppViewModelProvider.Factory), onValueChange: (Entry) -> Unit = {}, fun EditCategory(
onButtonClick: () -> Unit,
modifier: Modifier = Modifier,
editCategoryViewModel: EditCategoryViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
/*
val entry = editViewModel.editUiState.entry
val category = editViewModel.categoryUi.category
val categories by editViewModel.categoryListUiState.categories.collectAsState(initial = emptyList())
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) } // Controls dropdown visibility
val category = editCategoryViewModel.categoryUi.category
var selectedIconIndex = category.icon // Store index of selected icon
Log.d(
"kkjkjkjkj",
category.categoryName)
/*
val categories by categoryViewModel.categoryUiState.categories.collectAsState(initial = emptyList())
val category = categoryViewModel.categoryUi.category
var expanded by remember { mutableStateOf(false) }*/
Column( Column(
modifier = modifier.fillMaxSize() modifier = modifier
.fillMaxSize()
.padding(16.dp, 0.dp), .padding(16.dp, 0.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
Column( OutlinedTextField(
Modifier.weight(1f) value = category.categoryName,
onValueChange = { editCategoryViewModel.updateCategory(category.copy(categoryName = it)) },
label = { Text("Category Name") },
modifier = Modifier
.fillMaxWidth()
)
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = it }
) { ) {
OutlinedTextField( OutlinedTextField(
value = entry.name, value = iconNames[selectedIconIndex], // Show selected icon name
onValueChange = {editViewModel.updateEntry(entry.copy(name = it))}, onValueChange = {},
label = { Text("Name") }, label = { Text("Icon") },
modifier = Modifier readOnly = true,
.fillMaxWidth() leadingIcon = {
) Icon(
OutlinedTextField( imageVector = icons[selectedIconIndex], // Replace with your desired icon
value = entry.amount.toString(), contentDescription = "Leading Icon"
onValueChange = { editViewModel.updateEntry(entry.copy(amount = it.toFloat())) }, )
label = { Text("Spending") }, },
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
},
modifier = Modifier modifier = Modifier
.menuAnchor()
.fillMaxWidth() .fillMaxWidth()
) )
ExposedDropdownMenuBox( ExposedDropdownMenu(
expanded = expanded, expanded = expanded,
onExpandedChange = { expanded = it } onDismissRequest = { expanded = false }
) { ) {
// TextField to display the selected item and trigger the dropdown icons.forEachIndexed { index, icon ->
OutlinedTextField( DropdownMenuItem(
value = category.categoryName, text = { Text(text = iconNames[index]) }, // Use name from iconNames
onValueChange = {}, onClick = {
label = { Text("Category") }, selectedIconIndex = index // Update selected index
readOnly = true,
trailingIcon = {
TrailingIcon(expanded = expanded)
},
modifier = Modifier
.menuAnchor()
.fillMaxWidth()
)
// Dropdown menu category.copy(_id = index)
ExposedDropdownMenu( editCategoryViewModel.updateCategory(category)
expanded = expanded, expanded = false
onDismissRequest = { expanded = false } },
) { leadingIcon = {
categories.forEach { item -> androidx.compose.material3.Icon(
DropdownMenuItem( imageVector = icon,
text = { Text(text = item.categoryName) }, contentDescription = iconNames[index]
onClick = { )
entry.copy(categoryID = item._id) }
editViewModel.updateEntry(entry) )
expanded = false
}
)
}
} }
} }
Log.w("xaver", entry.date.toString())
DatePickerDocked(entry){
dateMilis -> editViewModel.updateEntry(entry.copy(date = dateMilis))
}
} }
Column( Box(
modifier = Modifier.fillMaxWidth(), modifier = Modifier
horizontalAlignment = Alignment.CenterHorizontally // Center buttons horizontally .fillMaxWidth(),
contentAlignment = Alignment.Center
) { ) {
ButtonDanger(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 8.dp),
text = "Delete",
onClick = { onCardClick() }
)
ButtonSuccess( ButtonSuccess(
modifier = Modifier.fillMaxWidth(), // Add spacing between buttons modifier = Modifier,
text = "Done", "Edit Category",
onClick = { onClick = {
editViewModel.saveEntry() editCategoryViewModel.saveCategory()
onCardClick() onButtonClick()
} }
) )
} }
}*/ }
} }

View File

@ -0,0 +1,66 @@
package at.xaxa.ledger.ui.category.edit
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import at.xaxa.ledger.data.Entry
import at.xaxa.ledger.data.EntryRepository
import at.xaxa.ledger.data.db.Category.CategoryEntity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
data class CategoryUIState(val category: CategoryEntity = CategoryEntity(0,"",0))
class EditCategoryViewModel(private val savedStateHandle: SavedStateHandle,
private val entryRepository: EntryRepository
) : ViewModel() {
private val categoryId: Int = checkNotNull(savedStateHandle["categoryId"])
var categoryUiState by mutableStateOf(CategoryUIState())
var categoryUi by mutableStateOf(CategoryUIState())
private set
init {
viewModelScope.launch {
val category = withContext(Dispatchers.IO) {
entryRepository.findCategoryById(categoryId)
}
categoryUi = CategoryUIState(category)
}
}
fun updateCategory(category: CategoryEntity) {
categoryUi = categoryUi.copy(category = category)
}
fun onDeleteEntry(category: CategoryEntity) {
viewModelScope.launch {
entryRepository.deleteCategory(category)
}
}
fun saveCategory() {
viewModelScope.launch {
entryRepository.updateCategory(categoryUi.category)
}
}
fun findCategoryByID(categoryId: Int) {
viewModelScope.launch {
val category = withContext(Dispatchers.IO) {
entryRepository.findCategoryById(categoryId)
}
categoryUi = CategoryUIState(category)
}
}
}

View File

@ -61,23 +61,6 @@ class AddViewModel(
} }
} }
fun addCategory(category: CategoryEntity) {
viewModelScope.launch {
try {
val categoryEntity = CategoryEntity(
_id = category._id,
categoryName = category.categoryName,
icon = category.icon,
)
withContext(Dispatchers.IO) {
repository.insertCategory(categoryEntity) // Add game to the database
}
// Optionally, log or update UI state to reflect that the game was added
} catch (e: Exception) {
}
}
}
fun getAllCategories() { fun getAllCategories() {
viewModelScope.launch { viewModelScope.launch {