diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/AppViewModelProvider.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/AppViewModelProvider.kt index 26cc562..72b1cd7 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/AppViewModelProvider.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/AppViewModelProvider.kt @@ -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) + } } } \ No newline at end of file diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerApp.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerApp.kt index e78b0cb..7fc5d75 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerApp.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerApp.kt @@ -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") + } + ) + } } } -} \ No newline at end of file +} + diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerUI.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerUI.kt index 48b35a9..1e6138c 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerUI.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/LedgerUI.kt @@ -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( diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryUI.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryUI.kt index e1eff0e..5f91e6b 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryUI.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryUI.kt @@ -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) } + ) + } + } + } + } +} + + + + diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryViewModel.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryViewModel.kt index e1eff0e..af555ac 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryViewModel.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/category/CategoryViewModel.kt @@ -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> = 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) + } + } +} diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditUI.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditUI.kt index fa39467..0b77805 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditUI.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditUI.kt @@ -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()) diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditViewModel.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditViewModel.kt index 25f0d70..8c45b83 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditViewModel.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/edit/EditViewModel.kt @@ -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, diff --git a/Ledger/app/src/main/java/at/xaxa/ledger/ui/home/HomeUI.kt b/Ledger/app/src/main/java/at/xaxa/ledger/ui/home/HomeUI.kt index 618f2cb..9b300ce 100644 --- a/Ledger/app/src/main/java/at/xaxa/ledger/ui/home/HomeUI.kt +++ b/Ledger/app/src/main/java/at/xaxa/ledger/ui/home/HomeUI.kt @@ -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(