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

# Conflicts:
#	Ledger/app/src/main/java/at/xaxa/ledger/data/EntryRepository.kt
#	Ledger/app/src/main/java/at/xaxa/ledger/data/db/LedgerDao.kt
#	Ledger/app/src/main/java/at/xaxa/ledger/ui/category/edit/EditCategory.kt
#	Ledger/app/src/main/java/at/xaxa/ledger/ui/entry/add/AddUI.kt
#	Ledger/app/src/main/java/at/xaxa/ledger/ui/home/HomeUI.kt
#	Ledger/app/src/main/java/at/xaxa/ledger/ui/home/HomeViewModel.kt
This commit is contained in:
Florian 2025-01-17 09:50:14 +01:00
commit f97adc39eb
6 changed files with 57 additions and 37 deletions

View File

@ -27,6 +27,10 @@ class EntryRepository(private val ledgerDao: LedgerDao){
return ledgerDao.findEntryByCategoryId(id) return ledgerDao.findEntryByCategoryId(id)
} }
suspend fun calculateBalance(): Float{
return ledgerDao.calculateBalance()
}
suspend fun findEntryById(id: Int): Entry { suspend fun findEntryById(id: Int): Entry {
val entry = ledgerDao.findEntryById(id) val entry = ledgerDao.findEntryById(id)
return Entry( return Entry(

View File

@ -51,6 +51,9 @@ interface LedgerDao {
@Query("SELECT * FROM _transaction") @Query("SELECT * FROM _transaction")
fun getAllEntries(): Flow<List<EntryEntity>> fun getAllEntries(): Flow<List<EntryEntity>>
@Query("SELECT SUM(amount) From _transaction")
suspend fun calculateBalance(): Float
@Query("SELECT * FROM _transaction INNER JOIN category ON _transaction.categoryID = category._id") @Query("SELECT * FROM _transaction INNER JOIN category ON _transaction.categoryID = category._id")
fun getAllBigEntries(): Flow<List<BigEntity>> fun getAllBigEntries(): Flow<List<BigEntity>>
} }

View File

@ -60,7 +60,6 @@ class AddViewModel(
} }
} }
fun getAllCategories() { fun getAllCategories() {
viewModelScope.launch { viewModelScope.launch {
val categories = withContext(Dispatchers.IO) { val categories = withContext(Dispatchers.IO) {

View File

@ -16,6 +16,7 @@ import androidx.compose.material3.Text
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
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
@ -32,17 +33,25 @@ import at.xaxa.ledger.ui.category.iconNames
import at.xaxa.ledger.ui.category.icons import at.xaxa.ledger.ui.category.icons
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun Edit(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel : EditViewModel = viewModel(factory = AppViewModelProvider.Factory), onValueChange: (Entry) -> Unit = {}) { fun Edit(
val entry = editViewModel.editUiState.entry modifier: Modifier = Modifier,
onCardClick: () -> Unit,
editViewModel: EditViewModel = viewModel(factory = AppViewModelProvider.Factory),
onValueChange: (Entry) -> Unit = {}
) {
val entry = editViewModel.editUiState.entry
val category = editViewModel.categoryUi.category val category = editViewModel.categoryUi.category
val categories by editViewModel.categoryListUiState.categories.collectAsState(initial = emptyList()) val categories by editViewModel.categoryListUiState.categories.collectAsState(initial = emptyList())
var selectedIconIndex by remember { mutableStateOf(0) } // Store index of selected icon var selectedIconIndex by remember { mutableStateOf(category.icon) } // Store index of selected icon
var selectedCategoryName by remember { mutableStateOf(category.categoryName) } // Store index of selected icon
var selectedCategory by remember { mutableIntStateOf(category.icon) }
var expanded by remember { mutableStateOf(false) } 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
) { ) {
@ -51,14 +60,19 @@ fun Edit(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel :
) { ) {
OutlinedTextField( OutlinedTextField(
value = entry.name, value = entry.name,
onValueChange = {editViewModel.updateEntry(entry.copy(name = it))}, onValueChange = { editViewModel.updateEntry(entry.copy(name = it)) },
label = { Text("Name") }, label = { Text("Name") },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
) )
OutlinedTextField( OutlinedTextField(
value = entry.amount.toString(), value = entry.amount.toString(),
onValueChange = { editViewModel.updateEntry(entry.copy(amount = it.toFloat())) }, onValueChange = {
val isValidSpending = it.matches(Regex("^[+-]?\\d*(\\.\\d{0,2})?$"))
if (isValidSpending){
editViewModel.updateEntry(entry.copy(amount = it.toFloat()))
}
},
label = { Text("Spending") }, label = { Text("Spending") },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -69,9 +83,9 @@ fun Edit(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel :
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(
@ -91,17 +105,19 @@ fun Edit(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel :
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]
) )
} }
) )
@ -109,8 +125,8 @@ fun Edit(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel :
} }
} }
DatePickerDocked(entry){ DatePickerDocked(entry) { dateMilis ->
dateMilis -> editViewModel.updateEntry(entry.copy(date = dateMilis)) editViewModel.updateEntry(entry.copy(date = dateMilis))
} }
} }

View File

@ -24,9 +24,10 @@ import at.xaxa.ledger.ui.convertMillisToDate
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun Home(modifier: Modifier = Modifier, onCardClick: (Int) -> Unit, onButtonClick: () -> Unit, onCatButtonClick: () -> Unit, HomeViewModel : HomeViewModel = viewModel(factory = AppViewModelProvider.Factory)) { fun Home(modifier: Modifier = Modifier, onCardClick: (Int) -> Unit, onButtonClick: () -> Unit, onCatButtonClick: () -> Unit, homeViewModel : HomeViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
val state by HomeViewModel.entryUIState.entry.collectAsState(initial = emptyList()) val state by homeViewModel.entryUIState.entry.collectAsState(initial = emptyList())
val category = HomeViewModel.categoryUi.category homeViewModel.calculateBalance()
val balance = homeViewModel.balance
Column( Column(
modifier = Modifier modifier = Modifier
@ -34,13 +35,12 @@ fun Home(modifier: Modifier = Modifier, onCardClick: (Int) -> Unit, onButtonClic
.padding(16.dp, 0.dp), .padding(16.dp, 0.dp),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
val items = (1..20).toList()
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
) { ) {
stickyHeader { stickyHeader {
HeaderCard(modifier = modifier, "-13563.00", onCatButtonClick) HeaderCard(modifier = modifier, balance.toString()+"", onCatButtonClick)
} }
items(state) { item -> items(state) { item ->
Column( Column(

View File

@ -1,6 +1,7 @@
package at.xaxa.ledger.ui.home package at.xaxa.ledger.ui.home
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -12,6 +13,8 @@ import at.xaxa.ledger.ui.category.add.CategoryListUIState
import at.xaxa.ledger.ui.category.edit.CategoryUIState import at.xaxa.ledger.ui.category.edit.CategoryUIState
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.forEach import kotlinx.coroutines.flow.forEach
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@ -21,16 +24,14 @@ import kotlinx.coroutines.withContext
data class EntryListUIState(val entry: Flow<List<BigEntity>> = flowOf(emptyList())) data class EntryListUIState(val entry: Flow<List<BigEntity>> = flowOf(emptyList()))
class HomeViewModel(private val repository: EntryRepository): ViewModel() { class HomeViewModel(private val repository: EntryRepository) : ViewModel() {
var categoryUi by mutableStateOf(CategoryUIState())
private set
var entryUIState by mutableStateOf(EntryListUIState()) var entryUIState by mutableStateOf(EntryListUIState())
var balance by mutableFloatStateOf(0.0f)
private set // Restrict external modification
init {
init{
viewModelScope.launch { viewModelScope.launch {
val entries = withContext(Dispatchers.IO){ val entries = withContext(Dispatchers.IO) {
repository.getAllBigEntries() repository.getAllBigEntries()
} }
entryUIState = EntryListUIState(entries) entryUIState = EntryListUIState(entries)
@ -39,12 +40,9 @@ class HomeViewModel(private val repository: EntryRepository): ViewModel() {
} }
/* fun findCategoryByID() { fun calculateBalance() {
viewModelScope.launch { viewModelScope.launch {
val category = withContext(Dispatchers.IO) { balance = repository.calculateBalance()
repository.findCategoryById(categoryId) }
} }
categoryUi = CategoryUIState(category)
}
}*/
} }