diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenu.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenu.kt index ba066f5..952a415 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenu.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/appskeleton/SideMenu.kt @@ -6,16 +6,18 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import bankmeister.composeapp.generated.resources.AppIcon import bankmeister.composeapp.generated.resources.Res +import kotlinx.coroutines.launch import net.codinux.banking.ui.composables.BanksList import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.DI +import net.codinux.banking.ui.model.BankAccountFilter import org.jetbrains.compose.resources.imageResource private val uiState = DI.uiState @@ -34,6 +36,8 @@ private val HeaderBackground = Brush.linearGradient( fun SideMenu(appContent: @Composable () -> Unit) { val drawerState = uiState.drawerState.collectAsState().value + val coroutineScope = rememberCoroutineScope() + ModalDrawer( modifier = Modifier.fillMaxHeight(), drawerState = drawerState, @@ -59,7 +63,17 @@ fun SideMenu(appContent: @Composable () -> Unit) { Text("Konten", color = Colors.DrawerPrimaryText) } - BanksList(textColor = Colors.DrawerPrimaryText) + BanksList(textColor = Colors.DrawerPrimaryText) { userAccount, bankAccount -> + uiState.accountFilter.value = if (userAccount == null) { + emptyList() + } else { + listOf(BankAccountFilter(userAccount, bankAccount)) + } + + coroutineScope.launch { + drawerState.close() + } + } } } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt index d8b3007..7dd8b83 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/BanksList.kt @@ -1,5 +1,6 @@ package net.codinux.banking.ui.composables +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -11,6 +12,8 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import bankmeister.composeapp.generated.resources.Res import bankmeister.composeapp.generated.resources.account +import net.codinux.banking.dataaccess.entities.BankAccountEntity +import net.codinux.banking.dataaccess.entities.UserAccountEntity import net.codinux.banking.ui.config.DI private val uiState = DI.uiState @@ -18,11 +21,22 @@ private val uiState = DI.uiState private val IconTextSpacing = 36.dp @Composable -fun BanksList(modifier: Modifier = Modifier, itemModifier: Modifier = Modifier.height(48.dp).widthIn(min = 300.dp).padding(start = 8.dp), iconSize: Dp = 24.dp, textColor: Color = Color.White) { +fun BanksList( + modifier: Modifier = Modifier, + iconSize: Dp = 24.dp, + textColor: Color = Color.White, + itemModifier: Modifier = Modifier.height(48.dp).widthIn(min = 300.dp).padding(start = 8.dp), + accountSelected: ((UserAccountEntity?, BankAccountEntity?) -> Unit)? = null +) { val userAccounts = uiState.userAccounts.collectAsState() Column(modifier) { - Row(itemModifier, verticalAlignment = Alignment.CenterVertically) { + Row( + itemModifier.clickable { + accountSelected?.invoke(null, null) + }, + verticalAlignment = Alignment.CenterVertically + ) { BankIcon(null as? String?, Modifier.padding(end = IconTextSpacing), Modifier.size(iconSize), fallbackIcon = Res.drawable.account) Text("Alle Konten", color = textColor) @@ -31,14 +45,24 @@ fun BanksList(modifier: Modifier = Modifier, itemModifier: Modifier = Modifier.h userAccounts.value.forEach { userAccount -> Spacer(Modifier.fillMaxWidth().height(12.dp)) - Row(itemModifier, verticalAlignment = Alignment.CenterVertically) { + Row( + itemModifier.clickable { + accountSelected?.invoke(userAccount, null) + }, + verticalAlignment = Alignment.CenterVertically + ) { BankIcon(userAccount, Modifier.padding(end = IconTextSpacing), Modifier.size(iconSize), fallbackIcon = Res.drawable.account) Text(userAccount.bankName, color = textColor) } userAccount.accounts.sortedBy { it.displayIndex }.forEach { account -> - Column(itemModifier.padding(start = iconSize + IconTextSpacing), verticalArrangement = Arrangement.Center) { + Column( + itemModifier.clickable { + accountSelected?.invoke(userAccount, account) + }.padding(start = iconSize + IconTextSpacing), + verticalArrangement = Arrangement.Center + ) { Text(account.productName ?: account.identifier, color = textColor) } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/TransactionsList.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/TransactionsList.kt index fbceebd..5f74789 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/TransactionsList.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/composables/TransactionsList.kt @@ -23,6 +23,8 @@ import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.state.UiState import org.jetbrains.compose.ui.tooling.preview.Preview +private val filterService = DI.bankAccountFilterService + private val formatUtil = DI.formatUtil @Composable @@ -32,10 +34,16 @@ fun TransactionsList(uiState: UiState) { derivedStateOf { userAccounts.associateBy { it.id } } } + val accountFilter by uiState.accountFilter.collectAsState() + val transactions by uiState.transactions.collectAsState() - val groupedByMonth by remember(transactions) { - derivedStateOf { transactions.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } } + val transactionsToDisplay by remember(accountFilter, transactions) { + derivedStateOf { filterService.filterAccounts(transactions, accountFilter) } + } + + val groupedByMonth by remember(transactionsToDisplay) { + derivedStateOf { transactionsToDisplay.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } } } LazyColumn( diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/config/DI.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/config/DI.kt index 1025a04..20d799d 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/config/DI.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/config/DI.kt @@ -24,6 +24,8 @@ object DI { val bankIconService = BankIconService() + val bankAccountFilterService = BankAccountFilterService() + var bankingRepository: BankingRepository = InMemoryBankingRepository(emptyList()) diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt new file mode 100644 index 0000000..02fad44 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/model/BankAccountFilter.kt @@ -0,0 +1,9 @@ +package net.codinux.banking.ui.model + +import net.codinux.banking.dataaccess.entities.BankAccountEntity +import net.codinux.banking.dataaccess.entities.UserAccountEntity + +data class BankAccountFilter( + val userAccount: UserAccountEntity, + val bankAccount: BankAccountEntity? = null +) \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankAccountFilterService.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankAccountFilterService.kt new file mode 100644 index 0000000..2141648 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankAccountFilterService.kt @@ -0,0 +1,24 @@ +package net.codinux.banking.ui.service + +import net.codinux.banking.ui.model.AccountTransactionViewModel +import net.codinux.banking.ui.model.BankAccountFilter + +class BankAccountFilterService { + + fun filterAccounts(transactions: List, accountsFilter: List): List = + if (accountsFilter.isEmpty()) { + transactions + } else { + transactions.filter { matchesFilter(it, accountsFilter) } + } + + private fun matchesFilter(transaction: AccountTransactionViewModel, accountsFilter: List): Boolean = + accountsFilter.any { (userAccount, bankAccount) -> + if (bankAccount != null) { + transaction.bankAccountId == bankAccount.id + } else { + transaction.userAccountId == userAccount.id + } + } + +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt index 8e0ec6e..dd8d90f 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/state/UiState.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import kotlinx.coroutines.flow.MutableStateFlow import net.codinux.banking.dataaccess.entities.UserAccountEntity import net.codinux.banking.ui.model.AccountTransactionViewModel +import net.codinux.banking.ui.model.BankAccountFilter import net.codinux.banking.ui.model.TanChallengeReceived import net.codinux.banking.ui.model.error.ApplicationError import net.codinux.banking.ui.model.error.BankingClientError @@ -21,6 +22,9 @@ class UiState : ViewModel() { val drawerState = MutableStateFlow(DrawerState(DrawerValue.Open)) + val accountFilter = MutableStateFlow>(emptyList()) + + val applicationErrorOccurred = MutableStateFlow(null) val bankingClientErrorOccurred = MutableStateFlow(null)