Merge remote-tracking branch 'origin/Xaver' into Florian

This commit is contained in:
Florian 2025-01-17 09:28:51 +01:00
commit b908de01ba
6 changed files with 157 additions and 78 deletions

View File

@ -34,7 +34,6 @@ class EntryRepository(private val ledgerDao: LedgerDao){
) )
} }
suspend fun findCategoryById(id: Int): CategoryEntity { suspend fun findCategoryById(id: Int): CategoryEntity {
Log.w("xaver", id.toString())
val category = ledgerDao.findCategoryById(id) val category = ledgerDao.findCategoryById(id)
return CategoryEntity( return CategoryEntity(
category._id, category.categoryName, category.icon category._id, category.categoryName, category.icon

View File

@ -46,59 +46,62 @@ fun AddCategory(
.padding(16.dp, 0.dp), .padding(16.dp, 0.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
OutlinedTextField( Column(
value = name, Modifier.weight(1f)
onValueChange = { name = it },
label = { Text("Category Name") },
modifier = Modifier
.fillMaxWidth()
)
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = it }
) { ) {
OutlinedTextField( OutlinedTextField(
value = iconNames[selectedIconIndex], // Show selected icon name value = name,
onValueChange = {}, onValueChange = { name = it },
label = { Text("Icon") }, label = { Text("Category Name") },
readOnly = true,
leadingIcon = {
Icon(
imageVector = icons[selectedIconIndex], // Replace with your desired icon
contentDescription = "Leading Icon"
)
},
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
},
modifier = Modifier modifier = Modifier
.menuAnchor()
.fillMaxWidth() .fillMaxWidth()
) )
ExposedDropdownMenu( ExposedDropdownMenuBox(
expanded = expanded, expanded = expanded,
onDismissRequest = { expanded = false } onExpandedChange = { expanded = it }
) { ) {
icons.forEachIndexed { index, icon -> OutlinedTextField(
DropdownMenuItem( value = iconNames[selectedIconIndex], // Show selected icon name
text = { Text(text = iconNames[index]) }, // Use name from iconNames onValueChange = {},
onClick = { label = { Text("Icon") },
selectedIconIndex = index // Update selected index readOnly = true,
expanded = false leadingIcon = {
}, Icon(
leadingIcon = { imageVector = icons[selectedIconIndex], // Replace with your desired icon
androidx.compose.material3.Icon( contentDescription = "Leading Icon"
imageVector = icon, )
contentDescription = iconNames[index] },
) trailingIcon = {
} ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
) },
modifier = Modifier
.menuAnchor()
.fillMaxWidth()
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
icons.forEachIndexed { index, icon ->
DropdownMenuItem(
text = { Text(text = iconNames[index]) }, // Use name from iconNames
onClick = {
selectedIconIndex = index // Update selected index
expanded = false
},
leadingIcon = {
androidx.compose.material3.Icon(
imageVector = icon,
contentDescription = iconNames[index]
)
}
)
}
} }
} }
} }
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth(), .fillMaxWidth(),

View File

@ -6,6 +6,9 @@ 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
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.AlertDialog
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
@ -13,6 +16,7 @@ import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon 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.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -40,22 +44,55 @@ fun EditCategory(
editCategoryViewModel: EditCategoryViewModel = viewModel(factory = AppViewModelProvider.Factory) editCategoryViewModel: EditCategoryViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
val category = editCategoryViewModel.categoryUi.category val category = editCategoryViewModel.categoryUi.category
var expanded by remember { mutableStateOf(false) } // Controls dropdown visibility var showError by remember { mutableStateOf(editCategoryViewModel.entryUIState) }
var selectedIconIndex by remember { mutableIntStateOf(category.icon) } // Store index of selected icon var deleteStarted by remember { mutableStateOf(false) }
var expanded by remember { mutableStateOf(false) }
var selectedIconIndex by remember { mutableIntStateOf(category.icon) }
LaunchedEffect(category) { LaunchedEffect(category) {
selectedIconIndex = category.icon selectedIconIndex = category.icon
} }
/* LaunchedEffect(deleteStarted) {
val categories by categoryViewModel.categoryUiState.categories.collectAsState(initial = emptyList()) if (deleteStarted) {
val category = categoryViewModel.categoryUi.category editCategoryViewModel.findEntryByCategoryId()
var expanded by remember { mutableStateOf(false) }*/ showError = editCategoryViewModel.entryUIState
}
}
if (deleteStarted && showError) {
AlertDialog(
icon = {
Icon(Icons.Default.Info, contentDescription = "Info Icon")
},
title = {
Text(text = "Category in use")
},
text = {
Text(text = "You are trying to delete a Category which is still in use. Please delete or change the Category in your entries which are in use.")
},
onDismissRequest = {
deleteStarted = false
showError = false
},
confirmButton = {
TextButton(
onClick = {
deleteStarted = false
showError = false
}
) {
Text("Okay")
}
}
)
}else if(deleteStarted && !showError){
Log.w("xaver", "delete")
editCategoryViewModel.deleteEntry()
onButtonClick()
}
Log.w("vm", category.categoryName.toString()) Log.w("xaver", "deleteStarted $deleteStarted : showError $showError" )
Log.w("vm", category.icon.toString())
Log.w("vm", selectedIconIndex.toString())
Column( Column(
modifier = modifier modifier = modifier
@ -79,13 +116,13 @@ fun EditCategory(
onExpandedChange = { expanded = it } onExpandedChange = { expanded = it }
) { ) {
OutlinedTextField( OutlinedTextField(
value = iconNames[selectedIconIndex], // Show selected icon name value = iconNames[selectedIconIndex],
onValueChange = {}, onValueChange = {},
label = { Text("Icon") }, label = { Text("Icon") },
readOnly = true, readOnly = true,
leadingIcon = { leadingIcon = {
Icon( Icon(
imageVector = icons[selectedIconIndex], // Replace with your desired icon imageVector = icons[selectedIconIndex],
contentDescription = "Leading Icon" contentDescription = "Leading Icon"
) )
}, },
@ -103,10 +140,9 @@ fun EditCategory(
) { ) {
icons.forEachIndexed { index, icon -> icons.forEachIndexed { index, icon ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(text = iconNames[index]) }, // Use name from iconNames text = { Text(text = iconNames[index]) },
onClick = { onClick = {
selectedIconIndex = index // Update selected index selectedIconIndex = index
editCategoryViewModel.updateCategory(category.copy(icon = index)) editCategoryViewModel.updateCategory(category.copy(icon = index))
expanded = false expanded = false
}, },
@ -124,23 +160,21 @@ fun EditCategory(
Column( Column(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally // Center buttons horizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
ButtonDanger( ButtonDanger(
modifier = Modifier modifier = Modifier
.padding(bottom = 8.dp), .padding(bottom = 8.dp),
"Delete Category", "Delete Category",
onClick = { onClick = {
editCategoryViewModel.deleteEntry() deleteStarted = true
onButtonClick() editCategoryViewModel.findEntryByCategoryId()
} }
) )
ButtonSuccess( ButtonSuccess(
modifier = Modifier, modifier = Modifier,
"Save Category", "Save Category",
onClick = { onClick = {
editCategoryViewModel.findEntryByCategoryId()
Log.d("dsdsssee", editCategoryViewModel.entryUIState.toString())
editCategoryViewModel.saveCategory() editCategoryViewModel.saveCategory()
onButtonClick() onButtonClick()
} }

View File

@ -29,7 +29,7 @@ class EditCategoryViewModel(private val savedStateHandle: SavedStateHandle, priv
var categoryUi by mutableStateOf(CategoryUIState()) var categoryUi by mutableStateOf(CategoryUIState())
private set private set
var entryUIState by mutableStateOf(0) var entryUIState by mutableStateOf(false)
@ -71,10 +71,10 @@ class EditCategoryViewModel(private val savedStateHandle: SavedStateHandle, priv
val fetchedEntries = withContext(Dispatchers.IO) { val fetchedEntries = withContext(Dispatchers.IO) {
entryRepository.findEntryByCategoryId(categoryId) entryRepository.findEntryByCategoryId(categoryId)
} }
entryUIState = fetchedEntries
Log.w("ASASDADS", categoryId.toString()) if(fetchedEntries>0){
Log.w("ASASDADS", fetchedEntries.toString()) entryUIState = true
}
} }
//print("ASASDADS$categoryId") //print("ASASDADS$categoryId")
} }

View File

@ -25,7 +25,6 @@ class OverviewCategoryViewModel(
private val repository: EntryRepository private val repository: EntryRepository
) : ViewModel() { ) : ViewModel() {
var categoryUiState by mutableStateOf(CategoryListUIState()) var categoryUiState by mutableStateOf(CategoryListUIState())
var categoryUi by mutableStateOf(CategoryUIState())
private set private set
init { init {

View File

@ -1,10 +1,14 @@
package at.xaxa.ledger.ui.entry.add package at.xaxa.ledger.ui.entry.add
import android.util.Log
import androidx.compose.foundation.layout.Box 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
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.AlertDialog
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
@ -12,6 +16,7 @@ import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon 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.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -30,6 +35,7 @@ import at.xaxa.ledger.ui.ButtonSuccess
import at.xaxa.ledger.ui.DatePickerDocked import at.xaxa.ledger.ui.DatePickerDocked
import at.xaxa.ledger.ui.category.iconNames import at.xaxa.ledger.ui.category.iconNames
import at.xaxa.ledger.ui.category.icons import at.xaxa.ledger.ui.category.icons
import kotlin.math.log
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -39,12 +45,41 @@ fun Add(
addViewModel: AddViewModel = viewModel(factory = AppViewModelProvider.Factory) addViewModel: AddViewModel = viewModel(factory = AppViewModelProvider.Factory)
) { ) {
var name by remember { mutableStateOf("") } var name by remember { mutableStateOf("") }
var categories = addViewModel.categoryUiState.categories.collectAsState(emptyList()).value
var spending by remember { mutableStateOf("") } var spending by remember { mutableStateOf("") }
var selectedDate by remember { mutableLongStateOf(0) } var selectedDate by remember { mutableLongStateOf(System.currentTimeMillis()) }
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
var selectedIconIndex by remember { mutableStateOf(0) } // Store index of selected icon var selectedIconIndex by remember { mutableStateOf(0) } // Store index of selected icon
var selectedCategoryName by remember { mutableStateOf("") } // Store index of selected icon
var selectedCategory by remember { mutableIntStateOf(-1) } var selectedCategory by remember { mutableIntStateOf(-1) }
var parsingError by remember { mutableStateOf(false) }
if (parsingError) {
AlertDialog(
icon = {
Icon(Icons.Default.Info, contentDescription = "Info Icon")
},
title = {
Text(text = "Parsing error")
},
text = {
Text(text = "One or more fields contain invalid input. Please review your entries and try again.")
},
onDismissRequest = {
parsingError = false
},
confirmButton = {
TextButton(
onClick = {
parsingError = false
}
) {
Text("Okay")
}
}
)
}
Column( Column(
modifier = modifier modifier = modifier
@ -76,9 +111,9 @@ fun Add(
onExpandedChange = { expanded = it } onExpandedChange = { expanded = it }
) { ) {
OutlinedTextField( OutlinedTextField(
value = iconNames[selectedIconIndex], // Show selected icon name value = selectedCategoryName, // Show selected icon name
onValueChange = {}, onValueChange = {},
label = { Text("Icon") }, label = { Text("Category") },
readOnly = true, readOnly = true,
leadingIcon = { leadingIcon = {
Icon( Icon(
@ -98,17 +133,19 @@ fun Add(
expanded = expanded, expanded = expanded,
onDismissRequest = { expanded = false } onDismissRequest = { expanded = false }
) { ) {
icons.forEachIndexed { index, icon -> categories.forEachIndexed { index, category ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(text = iconNames[index]) }, // Use name from iconNames text = { Text(text = category.categoryName) }, // Use name from iconNames
onClick = { onClick = {
selectedIconIndex = index // Update selected index selectedIconIndex = category.icon // Update selected index
expanded = false expanded = false
selectedCategoryName = category.categoryName
selectedCategory = category._id
}, },
leadingIcon = { leadingIcon = {
androidx.compose.material3.Icon( androidx.compose.material3.Icon(
imageVector = icon, imageVector = icons[category.icon],
contentDescription = iconNames[index] contentDescription = iconNames[category.icon]
) )
} }
) )
@ -116,8 +153,8 @@ fun Add(
} }
} }
DatePickerDocked{ DatePickerDocked { dateMilis ->
dateMilis -> selectedDate = dateMilis selectedDate = dateMilis
} }
} }
@ -130,7 +167,12 @@ fun Add(
modifier = Modifier, modifier = Modifier,
"Add Transaction", "Add Transaction",
onClick = { onClick = {
if (name.isNotBlank() && spending.toFloat() != 0f && selectedDate != 0L && selectedCategory != -1) { val isValidSpending = spending.matches(Regex("^[+-]?\\d*(\\.\\d+)?$"))
Log.w("xaxaxa", name.isNotBlank().toString() )
Log.w("xaxaxa", isValidSpending.toString() )
Log.w("xaxaxa", (selectedDate != 0L).toString() )
Log.w("xaxaxa", (selectedCategory != -1).toString() )
if (name.isNotBlank() && isValidSpending && selectedDate != 0L && selectedCategory != -1) {
val newEntry = Entry( val newEntry = Entry(
id = 0, id = 0,
name = name, name = name,
@ -140,6 +182,8 @@ fun Add(
) )
addViewModel.addEntryToDB(newEntry) addViewModel.addEntryToDB(newEntry)
onCardClick() onCardClick()
} else {
parsingError = true;
} }
} }
) )