Merge remote-tracking branch 'origin/Florian'

This commit is contained in:
Xaver 2025-01-15 15:51:25 +01:00
commit 013732322a
8 changed files with 235 additions and 5 deletions

View File

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

View File

@ -13,13 +13,15 @@ import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import at.xaxa.ledger.ui.add.Add
import at.xaxa.ledger.ui.category.addCategory
import at.xaxa.ledger.ui.edit.Edit
import at.xaxa.ledger.ui.home.Home
enum class AppRoutes(val route: String) {
Home("home"),
Add("add"),
Edit("edit/{entryId}")
Edit("edit/{entryId}"),
Category("category")
}
@Composable
@ -41,6 +43,9 @@ fun LedgerApp(modifier: Modifier = Modifier){
},
onButtonClick = {
navController.navigate("add")
},
onCatButtonClick = {
navController.navigate("category")
}
)
}
@ -64,6 +69,14 @@ fun LedgerApp(modifier: Modifier = Modifier){
}
)
}
composable(AppRoutes.Category.route){
addCategory(
onButtonClick = {
navController.navigate("home")
}
)
}
}
}
}
}

View File

@ -141,6 +141,27 @@ fun HorizontalCard(modifier: Modifier = Modifier, name: String, date: String, am
}
}
@Composable
fun CategoryCard(modifier: Modifier = Modifier, name: String, icon : Int, onClick: () -> Unit ) {
Surface(
onClick = onClick,
shape = RoundedCornerShape(12.dp),
color = Color(0xfff9f9f9),
border = BorderStroke(1.dp, Color(0xffc6c6c6)),
modifier = modifier
.clip(shape = RoundedCornerShape(12.dp))
) {
Row(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
LayoutMediaText(modifier, name, date, amount)
}
}
}
@Composable
fun LayoutMediaText(modifier: Modifier = Modifier, name: String, date: String, amount:String) {
Row(

View File

@ -1,2 +1,108 @@
package at.xaxa.ledger.ui.category
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import at.xaxa.ledger.data.db.Category.CategoryEntity
import at.xaxa.ledger.ui.AppViewModelProvider
import at.xaxa.ledger.ui.ButtonSuccess
import at.xaxa.ledger.ui.CategoryCard
import at.xaxa.ledger.ui.HorizontalCard
import at.xaxa.ledger.ui.convertMillisToDate
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun addCategory(
onButtonClick: () -> Unit,
modifier: Modifier = Modifier,
categoryViewModel: CategoryViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
var name by remember { mutableStateOf("") }
var icon by remember { mutableStateOf(0) }
val categories by categoryViewModel.categoryUiState.categories.collectAsState(initial = emptyList())
val category = categoryViewModel.categoryUi.category
var expanded by remember { mutableStateOf(false) }
Column(
modifier = modifier
.fillMaxSize()
.padding(16.dp, 0.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
LazyColumn(
Modifier.weight(1f)
) {
OutlinedTextField(
value = category.categoryName,
onValueChange = { name = it },
label = { Text("Name") },
modifier = Modifier
.fillMaxWidth()
)
OutlinedTextField(
value = category.icon.toString(),
onValueChange = { category.copy(icon = it.toInt()) },
label = { Text("Icon") },
modifier = Modifier
.fillMaxWidth()
)
Box(
modifier = Modifier
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
ButtonSuccess(
modifier = Modifier,
"Add Category",
onClick = {
if (name.isNotBlank()) {
val newCategory = CategoryEntity(
_id = 0,
categoryName = name,
icon = icon
)
categoryViewModel.addCategory(newCategory)
onButtonClick()
}
}
)
}
items(categories) { item ->
Column(
modifier = Modifier.padding(vertical = 4.dp)
) {
CategoryCard(
modifier = modifier,
name = category.categoryName,
icon = category.icon,
onClick = { onCardClick(category._id) }
)
}
}
}
}
}

View File

@ -1,2 +1,71 @@
package at.xaxa.ledger.ui.category
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.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
data class CategoryUIState(val category: CategoryEntity = CategoryEntity(0,"",0))
data class CategoryListUIState(val categories: Flow<List<CategoryEntity>> = flowOf(emptyList()))
class CategoryViewModel(
private val savedStateHandle: SavedStateHandle,
private val repository: EntryRepository
) : ViewModel() {
var categoryUiState by mutableStateOf(CategoryListUIState())
var categoryUi by mutableStateOf(CategoryUIState())
private set
init {
getAllCategories()
}
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() {
viewModelScope.launch {
val categories = withContext(Dispatchers.IO) {
repository.getAllCategories()
}
categoryUiState = CategoryListUIState(categories)
}
}
fun findCategoryByID(categoryId: Int) {
viewModelScope.launch {
val category = withContext(Dispatchers.IO) {
repository.findCategoryById(categoryId)
}
categoryUi = CategoryUIState(category)
}
}
}

View File

@ -21,6 +21,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import at.xaxa.ledger.data.Entry
import at.xaxa.ledger.ui.AppViewModelProvider
import at.xaxa.ledger.ui.ButtonDanger
import at.xaxa.ledger.ui.ButtonSuccess
@ -28,7 +29,8 @@ import at.xaxa.ledger.ui.DatePickerDocked
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Edit(modifier: Modifier = Modifier, onCardClick: () -> Unit, editViewModel : EditViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
fun Edit(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 categories by editViewModel.categoryListUiState.categories.collectAsState(initial = emptyList())

View File

@ -21,7 +21,7 @@ data class CategoryUIState(val category: CategoryEntity = CategoryEntity(0,"",0)
data class EditUI(
val entry: Entry = Entry(0, "", 0.0f, 0, 0)
val entry: Entry = Entry(0, "AS", 0.0f, 0, 0)
)
class EditViewModel(private val savedStateHandle: SavedStateHandle,

View File

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
@ -23,7 +24,7 @@ import at.xaxa.ledger.ui.convertMillisToDate
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Home(modifier: Modifier = Modifier, onCardClick: (Int) -> Unit, onButtonClick: () -> 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())
Column(
@ -39,6 +40,20 @@ fun Home(modifier: Modifier = Modifier, onCardClick: (Int) -> Unit, onButtonClic
) {
stickyHeader {
HeaderCard(modifier = modifier, "-13563.00€")
Box(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp), // Add slight padding from the header
contentAlignment = Alignment.TopStart // Align button to the top-left
) {
ButtonSuccess(
modifier = Modifier
.width(120.dp) // Make the button smaller
.padding(4.dp), // Add some padding for better touch area
text = "Add Category",
onClick = { onCatButtonClick() }
)
}
}
items(state) { item ->
Column(