From d0ed2622272596703e6827881a2dbd274f8b4734 Mon Sep 17 00:00:00 2001 From: Yuriy Kulikov Date: Thu, 4 Jul 2024 20:56:34 +0200 Subject: [PATCH] feat: better monthly grouping --- app-android/build.gradle.kts | 4 +- .../tracker/compose/NavigationBottomBar.kt | 2 +- .../java/simple/payment/tracker/compose/UI.kt | 8 ++- .../tracker/desktop/NavigationBottomBar.kt | 6 +- .../simple/payment/tracker/desktop/UI.kt | 13 ++-- .../tracker/compose/MonthlyGrouping.kt | 28 +++++++++ .../payment/tracker/compose/MonthlyScreen.kt | 63 ++++++++++++++----- 7 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyGrouping.kt diff --git a/app-android/build.gradle.kts b/app-android/build.gradle.kts index 8858a29..47a2081 100644 --- a/app-android/build.gradle.kts +++ b/app-android/build.gradle.kts @@ -14,8 +14,8 @@ android { applicationId = "simple.payment.tracker" minSdk = 28 targetSdk = 34 - versionCode = 10801 - versionName = "1.08.01" + versionCode = 10901 + versionName = "1.09.01" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled = true } diff --git a/app-android/src/main/java/simple/payment/tracker/compose/NavigationBottomBar.kt b/app-android/src/main/java/simple/payment/tracker/compose/NavigationBottomBar.kt index fad636e..b803c2e 100644 --- a/app-android/src/main/java/simple/payment/tracker/compose/NavigationBottomBar.kt +++ b/app-android/src/main/java/simple/payment/tracker/compose/NavigationBottomBar.kt @@ -38,7 +38,7 @@ fun NavigationBottomBar(currentScreen: MutableState) { IconButton( onClick = { currentScreen.value = Screen.Regular }, modifier = Modifier.weight(1f).highlightIf(currentScreen, Screen.Regular)) { - Text(text = "Reg") + Text(text = "Month") } IconButton( diff --git a/app-android/src/main/java/simple/payment/tracker/compose/UI.kt b/app-android/src/main/java/simple/payment/tracker/compose/UI.kt index 7901b60..0cfe1de 100644 --- a/app-android/src/main/java/simple/payment/tracker/compose/UI.kt +++ b/app-android/src/main/java/simple/payment/tracker/compose/UI.kt @@ -216,7 +216,9 @@ private fun AppContent( list.value, firebaseSignIn.signedInUserEmail(), bottomBar, - showMonthDetails = { monthDetailsToShow.value = Screen.MonthDetails(it) }) + showMonthDetails = { monthDetailsToShow.value = Screen.MonthDetails(it) }, + MonthlyGrouping.DEFAULT, + ) } is Screen.Irregular -> { val list: State> = @@ -226,7 +228,9 @@ private fun AppContent( list.value, firebaseSignIn.signedInUserEmail(), bottomBar, - showMonthDetails = { monthDetailsToShow.value = Screen.MonthDetails(it) }) + showMonthDetails = { monthDetailsToShow.value = Screen.MonthDetails(it) }, + MonthlyGrouping.NONE, + ) } is Screen.MonthDetails -> GroupDetailsScreen( diff --git a/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/NavigationBottomBar.kt b/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/NavigationBottomBar.kt index 85941ea..f33579f 100644 --- a/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/NavigationBottomBar.kt +++ b/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/NavigationBottomBar.kt @@ -32,9 +32,9 @@ fun NavigationBottomBar(currentScreen: Screen?, onChange: (Screen) -> Unit) { } IconButton( - onClick = { onChange(Screen.Regular) }, - modifier = Modifier.weight(1f).highlightIf(currentScreen, Screen.Regular)) { - Text(text = "Regular") + onClick = { onChange(Screen.Monthly) }, + modifier = Modifier.weight(1f).highlightIf(currentScreen, Screen.Monthly)) { + Text(text = "Monthly") } IconButton( diff --git a/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/UI.kt b/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/UI.kt index 6140c9b..808f791 100644 --- a/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/UI.kt +++ b/app-desktop/src/jvmMain/kotlin/simple/payment/tracker/desktop/UI.kt @@ -64,6 +64,7 @@ import simple.payment.tracker.TripStatistics import simple.payment.tracker.compose.DetailsScreen import simple.payment.tracker.compose.GroupDetailsScreen import simple.payment.tracker.compose.InboxList +import simple.payment.tracker.compose.MonthlyGrouping import simple.payment.tracker.compose.MonthlyScreen import simple.payment.tracker.compose.TransactionsList import simple.payment.tracker.compose.TripsScreen @@ -81,7 +82,7 @@ sealed interface Screen { object ListAll : Screen - object Regular : Screen + object Monthly : Screen object Irregular : Screen @@ -323,15 +324,16 @@ private fun LeftCrossFade( search = search, listState = allListState, ) - is Screen.Regular -> { + is Screen.Monthly -> { val list: State> = - remember { monthlyStatistics.reports(GroupReport.Type.REGULAR) } + remember { monthlyStatistics.reports(GroupReport.Type.ALL) } .collectAsState(initial = emptyList()) MonthlyScreen( list.value, userNameStore.data.stateIn(scope, SharingStarted.Eagerly, ""), bottomBar, - showMonthDetails) + showMonthDetails, + MonthlyGrouping.DEFAULT) } is Screen.Irregular -> { val list: State> = @@ -341,7 +343,8 @@ private fun LeftCrossFade( list.value, userNameStore.data.stateIn(scope, SharingStarted.Eagerly, ""), bottomBar, - showMonthDetails) + showMonthDetails, + MonthlyGrouping.NONE) } is Screen.Trips -> TripsScreen( diff --git a/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyGrouping.kt b/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyGrouping.kt new file mode 100644 index 0000000..788d64f --- /dev/null +++ b/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyGrouping.kt @@ -0,0 +1,28 @@ +package simple.payment.tracker.compose + +interface MonthlyGrouping { + fun group(category: String): Grouping + + data class Grouping(val group: String, val prio: Int) + + companion object { + val NONE: (String) -> Grouping = { Grouping("", 0) } + val DEFAULT: (String) -> Grouping = { category -> + when (category) { + "Жилье", + "Машина", + "Садик", + "Интернет" -> Grouping("Constant", 0) + "Еда", + "Ресторан", + "Гедонизм", + "Кот", + "Образование", + "Няня", + "Фитнесс", + "Drogerie" -> Grouping("Regular", 2) + else -> Grouping("Irregular", 1) + } + } + } +} diff --git a/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyScreen.kt b/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyScreen.kt index 53f3140..6feab77 100644 --- a/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyScreen.kt +++ b/compose-common/src/jvmMain/kotlin/simple/payment/tracker/compose/MonthlyScreen.kt @@ -28,6 +28,7 @@ fun MonthlyScreen( userName: StateFlow, bottomBar: @Composable () -> Unit, showMonthDetails: (GroupReport) -> Unit, + grouping: (String) -> MonthlyGrouping.Grouping, ) { Scaffold( topBar = { @@ -39,7 +40,8 @@ fun MonthlyScreen( bottomBar = bottomBar, content = { paddingValues -> val name = userName.collectAsState().value - StatisticsContent(Modifier.padding(paddingValues), reports, showMonthDetails, name ?: "") + StatisticsContent( + Modifier.padding(paddingValues), reports, showMonthDetails, name ?: "", grouping) }, ) } @@ -61,7 +63,13 @@ fun TripsScreen( val list: State> = remember { tripStatistics.reports() }.collectAsState(initial = emptyList()) - StatisticsContent(Modifier.padding(paddingValues), list.value, showTripDetails, name ?: "") + StatisticsContent( + Modifier.padding(paddingValues), + list.value, + showTripDetails, + name ?: "", + MonthlyGrouping.DEFAULT, + ) }, ) } @@ -72,11 +80,12 @@ private fun StatisticsContent( reports: List, showMonthDetails: (GroupReport) -> Unit, username: String, + grouping: (String) -> MonthlyGrouping.Grouping, ) { LazyColumn(modifier = modifier.fillMaxSize().padding(horizontal = 16.dp)) { items(reports) { stats -> - MonthEntry(stats, username, showMonthDetails) + MonthEntry(stats, username, showMonthDetails, grouping) ListDivider() } } @@ -90,7 +99,8 @@ private fun GroupReport.categorySums(forCat: String, forUser: String): Int { private fun MonthEntry( stats: GroupReport, username: String, - showMonthDetails: (GroupReport) -> Unit + showMonthDetails: (GroupReport) -> Unit, + grouping: (String) -> MonthlyGrouping.Grouping, ) { Column(Modifier.clickable { showMonthDetails(stats) }) { Row(modifier = Modifier.padding(top = 8.dp)) { @@ -111,20 +121,41 @@ private fun MonthEntry( } } stats.categorySums - .sortedByDescending { (_, sum) -> sum } - .forEach { (cat, sum) -> - Row { - Column(Modifier.weight(2F)) { Text(cat, style = typography.body1) } - Column(Modifier.weight(1F)) { Text(sum.toString(), style = typography.body1) } - Column(Modifier.weight(1F)) { - Text( - stats - .categorySums(forCat = cat, forUser = username) - .takeIf { it != 0 } - ?.toString() ?: "", - style = typography.body2) + .map { (cat, sum) -> cat to sum } + .groupBy { (cat, _) -> grouping(cat) } + .entries + .sortedByDescending { (group, _) -> group.prio } + .forEach { (group, groupSums) -> + val (groupName, prio) = group + if (groupName.isNotEmpty()) { + Row { + Column(Modifier.weight(2F)) { Text(groupName, style = typography.h6) } + Column(Modifier.weight(1F)) { + Text( + groupSums.sumOf { it.second }.toString(), + style = typography.h6, + color = Theme.colors.textAccent, + ) + } + Column(Modifier.weight(1F)) {} } } + groupSums + .sortedByDescending { (_, sum) -> sum } + .forEach { (cat, sum) -> + Row { + Column(Modifier.weight(2F)) { Text(cat, style = typography.body1) } + Column(Modifier.weight(1F)) { Text(sum.toString(), style = typography.body1) } + Column(Modifier.weight(1F)) { + Text( + stats + .categorySums(forCat = cat, forUser = username) + .takeIf { it != 0 } + ?.toString() ?: "", + style = typography.body2) + } + } + } } } }