Grouping transactions by month

This commit is contained in:
dankito 2024-08-25 02:25:30 +02:00
parent 32657331f9
commit 3124bfc8f8
6 changed files with 75 additions and 10 deletions

View File

@ -1,5 +1,6 @@
package net.codinux.banking.ui package net.codinux.banking.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -17,10 +18,11 @@ import kotlinx.coroutines.launch
import net.codinux.banking.client.model.AccountTransaction import net.codinux.banking.client.model.AccountTransaction
import net.codinux.banking.ui.composables.TransactionsList import net.codinux.banking.ui.composables.TransactionsList
import net.codinux.banking.ui.service.BankingService import net.codinux.banking.ui.service.BankingService
import net.codinux.banking.ui.service.Colors
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
private val typography = Typography( private val typography = Typography(
body1 = TextStyle(fontSize = 14.sp) body1 = TextStyle(fontSize = 14.sp, color = Colors.Zinc700)
) )
private val bankService = BankingService() private val bankService = BankingService()
@ -36,7 +38,10 @@ fun App() {
} }
MaterialTheme(typography = typography) { MaterialTheme(typography = typography) {
Column(Modifier.fillMaxWidth().fillMaxHeight(), horizontalAlignment = Alignment.CenterHorizontally) { Column(
Modifier.fillMaxWidth().fillMaxHeight().background(color = Colors.Zinc100),
horizontalAlignment = Alignment.CenterHorizontally
) {
TransactionsList(transactions) TransactionsList(transactions)
} }
} }

View File

@ -10,9 +10,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import net.codinux.banking.client.model.AccountTransaction import net.codinux.banking.client.model.AccountTransaction
import net.codinux.banking.ui.service.FormatUtil import net.codinux.banking.ui.service.DI
private val formatUtil = FormatUtil() private val formatUtil = DI.formatUtil
@Composable @Composable
fun TransactionListItem(transaction: AccountTransaction, backgroundColor: Color) { fun TransactionListItem(transaction: AccountTransaction, backgroundColor: Color) {

View File

@ -1,32 +1,62 @@
package net.codinux.banking.ui.composables package net.codinux.banking.ui.composables
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.items
import androidx.compose.material.Divider import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.datetime.LocalDate
import net.codinux.banking.client.model.AccountTransaction import net.codinux.banking.client.model.AccountTransaction
import net.codinux.banking.ui.service.Colors import net.codinux.banking.ui.service.Colors
import net.codinux.banking.ui.service.DI
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
@Composable @Composable
fun TransactionsList(transactions: List<AccountTransaction>) { fun TransactionsList(transactions: List<AccountTransaction>) {
val groupedByMonth by remember(transactions) {
derivedStateOf { transactions.groupBy { LocalDate(it.valueDate.year, it.valueDate.monthNumber, 1) } }
}
LazyColumn( LazyColumn(
modifier = Modifier.padding(4.dp) modifier = Modifier.padding(4.dp)
) { ) {
itemsIndexed(transactions) { index, transaction -> items(groupedByMonth.keys.sortedDescending()) { month ->
TransactionListItem(transaction, if (index % 2 == 0) Colors.Zinc100_50 else Color.White) Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = DI.formatUtil.formatMonth(month),
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
modifier = Modifier.padding(top = 24.dp, bottom = 2.dp),
)
if (index < transactions.size) { Spacer(Modifier.height(4.dp))
val monthTransactions = groupedByMonth[month].orEmpty().sortedByDescending { it.valueDate }
Column(Modifier.background(Color.White)) { // LazyColumn inside LazyColumn is not allowed
monthTransactions.forEachIndexed { index, transaction ->
TransactionListItem(transaction, if (index % 2 == 1) Colors.Zinc100_50 else Color.Transparent)
if (index < monthTransactions.size - 1) {
Divider(color = Colors.Zinc200, thickness = 1.dp) Divider(color = Colors.Zinc200, thickness = 1.dp)
} }
} }
} }
} }
}
}
}
@Preview @Preview
@Composable @Composable

View File

@ -9,4 +9,6 @@ object Colors {
val Zinc200 = Color(228, 228, 231) val Zinc200 = Color(228, 228, 231)
val Zinc700 = Color(63, 63, 70)
} }

View File

@ -0,0 +1,7 @@
package net.codinux.banking.ui.service
object DI {
val formatUtil = FormatUtil()
}

View File

@ -2,6 +2,7 @@ package net.codinux.banking.ui.service
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import kotlinx.datetime.Month
import net.codinux.banking.client.model.Amount import net.codinux.banking.client.model.Amount
import net.codinux.banking.fints.extensions.toStringWithMinDigits import net.codinux.banking.fints.extensions.toStringWithMinDigits
@ -10,6 +11,26 @@ class FormatUtil {
fun formatDate(date: LocalDate): String = // TODO: find a better way fun formatDate(date: LocalDate): String = // TODO: find a better way
"${date.dayOfMonth.toStringWithMinDigits(2)}.${date.monthNumber.toStringWithMinDigits(2)}.${date.year.toString().substring(2)}" "${date.dayOfMonth.toStringWithMinDigits(2)}.${date.monthNumber.toStringWithMinDigits(2)}.${date.year.toString().substring(2)}"
fun formatMonth(date: LocalDate): String = // TODO: find a better way
"${getMonthName(date.month)} ${date.year}"
private fun getMonthName(month: Month): String = when (month) {
Month.JANUARY -> "Januar"
Month.FEBRUARY -> "Februar"
Month.MARCH -> "März"
Month.APRIL -> "April"
Month.MAY -> "Mai"
Month.JUNE -> "Juni"
Month.JULY -> "Juli"
Month.AUGUST -> "August"
Month.SEPTEMBER -> "September"
Month.OCTOBER -> "Oktober"
Month.NOVEMBER -> "November"
Month.DECEMBER -> "Dezember"
else -> "Irgendwas stimmt hier nicht"
}
fun formatAmount(amount: Amount, currency: String): String { // TODO: find a better way fun formatAmount(amount: Amount, currency: String): String { // TODO: find a better way
val parts = amount.amount.split('.') val parts = amount.amount.split('.')
val decimalPart = if (parts.size == 2) parts[1] else "00" val decimalPart = if (parts.size == 2) parts[1] else "00"