Filtering transactions on click on account item in SideMenu
This commit is contained in:
parent
572bd8e9d8
commit
ce5b99c290
|
@ -6,16 +6,18 @@ import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import bankmeister.composeapp.generated.resources.AppIcon
|
import bankmeister.composeapp.generated.resources.AppIcon
|
||||||
import bankmeister.composeapp.generated.resources.Res
|
import bankmeister.composeapp.generated.resources.Res
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import net.codinux.banking.ui.composables.BanksList
|
import net.codinux.banking.ui.composables.BanksList
|
||||||
import net.codinux.banking.ui.config.Colors
|
import net.codinux.banking.ui.config.Colors
|
||||||
import net.codinux.banking.ui.config.DI
|
import net.codinux.banking.ui.config.DI
|
||||||
|
import net.codinux.banking.ui.model.BankAccountFilter
|
||||||
import org.jetbrains.compose.resources.imageResource
|
import org.jetbrains.compose.resources.imageResource
|
||||||
|
|
||||||
private val uiState = DI.uiState
|
private val uiState = DI.uiState
|
||||||
|
@ -34,6 +36,8 @@ private val HeaderBackground = Brush.linearGradient(
|
||||||
fun SideMenu(appContent: @Composable () -> Unit) {
|
fun SideMenu(appContent: @Composable () -> Unit) {
|
||||||
val drawerState = uiState.drawerState.collectAsState().value
|
val drawerState = uiState.drawerState.collectAsState().value
|
||||||
|
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
ModalDrawer(
|
ModalDrawer(
|
||||||
modifier = Modifier.fillMaxHeight(),
|
modifier = Modifier.fillMaxHeight(),
|
||||||
drawerState = drawerState,
|
drawerState = drawerState,
|
||||||
|
@ -59,7 +63,17 @@ fun SideMenu(appContent: @Composable () -> Unit) {
|
||||||
Text("Konten", color = Colors.DrawerPrimaryText)
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.codinux.banking.ui.composables
|
package net.codinux.banking.ui.composables
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -11,6 +12,8 @@ import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import bankmeister.composeapp.generated.resources.Res
|
import bankmeister.composeapp.generated.resources.Res
|
||||||
import bankmeister.composeapp.generated.resources.account
|
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
|
import net.codinux.banking.ui.config.DI
|
||||||
|
|
||||||
private val uiState = DI.uiState
|
private val uiState = DI.uiState
|
||||||
|
@ -18,11 +21,22 @@ private val uiState = DI.uiState
|
||||||
private val IconTextSpacing = 36.dp
|
private val IconTextSpacing = 36.dp
|
||||||
|
|
||||||
@Composable
|
@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()
|
val userAccounts = uiState.userAccounts.collectAsState()
|
||||||
|
|
||||||
Column(modifier) {
|
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)
|
BankIcon(null as? String?, Modifier.padding(end = IconTextSpacing), Modifier.size(iconSize), fallbackIcon = Res.drawable.account)
|
||||||
|
|
||||||
Text("Alle Konten", color = textColor)
|
Text("Alle Konten", color = textColor)
|
||||||
|
@ -31,14 +45,24 @@ fun BanksList(modifier: Modifier = Modifier, itemModifier: Modifier = Modifier.h
|
||||||
userAccounts.value.forEach { userAccount ->
|
userAccounts.value.forEach { userAccount ->
|
||||||
Spacer(Modifier.fillMaxWidth().height(12.dp))
|
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)
|
BankIcon(userAccount, Modifier.padding(end = IconTextSpacing), Modifier.size(iconSize), fallbackIcon = Res.drawable.account)
|
||||||
|
|
||||||
Text(userAccount.bankName, color = textColor)
|
Text(userAccount.bankName, color = textColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
userAccount.accounts.sortedBy { it.displayIndex }.forEach { account ->
|
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)
|
Text(account.productName ?: account.identifier, color = textColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ import net.codinux.banking.ui.config.DI
|
||||||
import net.codinux.banking.ui.state.UiState
|
import net.codinux.banking.ui.state.UiState
|
||||||
import org.jetbrains.compose.ui.tooling.preview.Preview
|
import org.jetbrains.compose.ui.tooling.preview.Preview
|
||||||
|
|
||||||
|
private val filterService = DI.bankAccountFilterService
|
||||||
|
|
||||||
private val formatUtil = DI.formatUtil
|
private val formatUtil = DI.formatUtil
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -32,10 +34,16 @@ fun TransactionsList(uiState: UiState) {
|
||||||
derivedStateOf { userAccounts.associateBy { it.id } }
|
derivedStateOf { userAccounts.associateBy { it.id } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val accountFilter by uiState.accountFilter.collectAsState()
|
||||||
|
|
||||||
val transactions by uiState.transactions.collectAsState()
|
val transactions by uiState.transactions.collectAsState()
|
||||||
|
|
||||||
val groupedByMonth by remember(transactions) {
|
val transactionsToDisplay by remember(accountFilter, transactions) {
|
||||||
derivedStateOf { transactions.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } }
|
derivedStateOf { filterService.filterAccounts(transactions, accountFilter) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val groupedByMonth by remember(transactionsToDisplay) {
|
||||||
|
derivedStateOf { transactionsToDisplay.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
|
|
@ -24,6 +24,8 @@ object DI {
|
||||||
|
|
||||||
val bankIconService = BankIconService()
|
val bankIconService = BankIconService()
|
||||||
|
|
||||||
|
val bankAccountFilterService = BankAccountFilterService()
|
||||||
|
|
||||||
|
|
||||||
var bankingRepository: BankingRepository = InMemoryBankingRepository(emptyList())
|
var bankingRepository: BankingRepository = InMemoryBankingRepository(emptyList())
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -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<AccountTransactionViewModel>, accountsFilter: List<BankAccountFilter>): List<AccountTransactionViewModel> =
|
||||||
|
if (accountsFilter.isEmpty()) {
|
||||||
|
transactions
|
||||||
|
} else {
|
||||||
|
transactions.filter { matchesFilter(it, accountsFilter) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun matchesFilter(transaction: AccountTransactionViewModel, accountsFilter: List<BankAccountFilter>): Boolean =
|
||||||
|
accountsFilter.any { (userAccount, bankAccount) ->
|
||||||
|
if (bankAccount != null) {
|
||||||
|
transaction.bankAccountId == bankAccount.id
|
||||||
|
} else {
|
||||||
|
transaction.userAccountId == userAccount.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import net.codinux.banking.dataaccess.entities.UserAccountEntity
|
import net.codinux.banking.dataaccess.entities.UserAccountEntity
|
||||||
import net.codinux.banking.ui.model.AccountTransactionViewModel
|
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.TanChallengeReceived
|
||||||
import net.codinux.banking.ui.model.error.ApplicationError
|
import net.codinux.banking.ui.model.error.ApplicationError
|
||||||
import net.codinux.banking.ui.model.error.BankingClientError
|
import net.codinux.banking.ui.model.error.BankingClientError
|
||||||
|
@ -21,6 +22,9 @@ class UiState : ViewModel() {
|
||||||
val drawerState = MutableStateFlow(DrawerState(DrawerValue.Open))
|
val drawerState = MutableStateFlow(DrawerState(DrawerValue.Open))
|
||||||
|
|
||||||
|
|
||||||
|
val accountFilter = MutableStateFlow<List<BankAccountFilter>>(emptyList())
|
||||||
|
|
||||||
|
|
||||||
val applicationErrorOccurred = MutableStateFlow<ApplicationError?>(null)
|
val applicationErrorOccurred = MutableStateFlow<ApplicationError?>(null)
|
||||||
|
|
||||||
val bankingClientErrorOccurred = MutableStateFlow<BankingClientError?>(null)
|
val bankingClientErrorOccurred = MutableStateFlow<BankingClientError?>(null)
|
||||||
|
|
Loading…
Reference in New Issue