Skip to content
Snippets Groups Projects
Unverified Commit d2ed18be authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

refactor: history

parent 18e00af3
No related branches found
No related tags found
No related merge requests found
...@@ -40,6 +40,7 @@ import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator ...@@ -40,6 +40,7 @@ import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator
import androidx.navigation3.ui.NavDisplay import androidx.navigation3.ui.NavDisplay
import androidx.navigation3.ui.rememberSceneSetupNavEntryDecorator import androidx.navigation3.ui.rememberSceneSetupNavEntryDecorator
import de.chaosdorf.meteroid.ui.* import de.chaosdorf.meteroid.ui.*
import de.chaosdorf.meteroid.ui.history.HistoryRoute
import de.chaosdorf.meteroid.ui.purchase.PurchaseRoute import de.chaosdorf.meteroid.ui.purchase.PurchaseRoute
import de.chaosdorf.meteroid.viewmodel.* import de.chaosdorf.meteroid.viewmodel.*
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
......
/*
* The MIT License (MIT)
*
* Copyright (c) 2013-2025 Chaosdorf e.V.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.chaosdorf.meteroid.ui.history
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import de.chaosdorf.meteroid.viewmodel.HistoryViewModel
import de.chaosdorf.meteroid.viewmodel.Navigator
@Composable
fun HistoryRoute(
viewModel: HistoryViewModel,
navigator: Navigator,
contentPadding: PaddingValues,
) {
val transactions by viewModel.transactions.collectAsState()
LazyColumn(contentPadding = contentPadding) {
items(
transactions,
key = { "transaction-${it.transaction.serverId}-${it.transaction.transactionId}" },
contentType = { if (it.drink != null) "transaction-drink" else "transaction-generic" }
) { (transaction, drink) ->
TransactionHistoryItem(transaction, drink)
}
}
}
...@@ -22,36 +22,18 @@ ...@@ -22,36 +22,18 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
package de.chaosdorf.meteroid.ui package de.chaosdorf.meteroid.ui.history
import androidx.compose.foundation.Image 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.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AttachMoney
import androidx.compose.material.icons.filled.QuestionMark
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil3.compose.rememberAsyncImagePainter
import de.chaosdorf.meteroid.model.Drink import de.chaosdorf.meteroid.model.Drink
import de.chaosdorf.meteroid.model.Transaction import de.chaosdorf.meteroid.model.Transaction
import de.chaosdorf.meteroid.theme.secondaryGradient
import de.chaosdorf.meteroid.ui.common.PriceBadge import de.chaosdorf.meteroid.ui.common.PriceBadge
import de.chaosdorf.meteroid.viewmodel.HistoryViewModel
import de.chaosdorf.meteroid.viewmodel.Navigator
import kotlinx.datetime.TimeZone import kotlinx.datetime.TimeZone
import kotlinx.datetime.toJavaLocalDateTime import kotlinx.datetime.toJavaLocalDateTime
import kotlinx.datetime.toLocalDateTime import kotlinx.datetime.toLocalDateTime
...@@ -59,84 +41,38 @@ import java.math.BigDecimal ...@@ -59,84 +41,38 @@ import java.math.BigDecimal
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle import java.time.format.FormatStyle
@Composable
fun HistoryRoute(
viewModel: HistoryViewModel,
navigator: Navigator,
contentPadding: PaddingValues,
) {
val transactions by viewModel.transactions.collectAsState()
LazyColumn(contentPadding = contentPadding) {
items(
transactions,
key = { "transaction-${it.transaction.serverId}-${it.transaction.transactionId}" },
) { (transaction, drink) ->
TransactionHistoryItem(transaction, drink)
}
}
}
@Composable @Composable
fun TransactionHistoryItem( fun TransactionHistoryItem(
transaction: Transaction, transaction: Transaction,
drink: Drink?, drink: Drink?,
modifier: Modifier = Modifier modifier: Modifier = Modifier,
) { ) {
val timestamp = transaction.timestamp.toLocalDateTime(TimeZone.currentSystemDefault()) val timestamp = remember(transaction.timestamp) {
val timestamp = transaction.timestamp.toLocalDateTime(TimeZone.Companion.currentSystemDefault())
val formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT) val formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
formatter.format(timestamp.toJavaLocalDateTime())
}
val deposit = remember(transaction.difference) {
transaction.difference > BigDecimal.ZERO
}
ListItem( val label = remember(drink, deposit) {
headlineContent = { when {
val label = when {
drink != null -> drink.name drink != null -> drink.name
transaction.difference > BigDecimal.ZERO -> "Deposit" deposit -> "Deposit"
else -> "Unknown" else -> "Unknown"
} }
}
ListItem(
headlineContent = {
Text(label) Text(label)
}, },
supportingContent = { supportingContent = {
Text(formatter.format(timestamp.toJavaLocalDateTime())) Text(timestamp)
}, },
leadingContent = { leadingContent = {
Box( TransactionIcon(drink, deposit)
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
.aspectRatio(1.0f)
.background(MaterialTheme.colorScheme.secondaryGradient.verticalGradient())
) {
if (drink != null) {
val thumbPainter = rememberAsyncImagePainter(
drink.logoUrl
)
val originalPainter = rememberAsyncImagePainter(
drink.originalLogoUrl,
error = thumbPainter
)
Image(
painter = originalPainter,
contentDescription = null,
contentScale = ContentScale.Fit,
modifier = Modifier
.align(Alignment.Center)
.fillMaxSize()
)
} else if (transaction.difference > BigDecimal.ZERO) {
Icon(
Icons.Default.AttachMoney,
contentDescription = null,
modifier = Modifier.align(Alignment.Center)
)
} else {
Icon(
Icons.Default.QuestionMark,
contentDescription = null,
modifier = Modifier.align(Alignment.Center)
)
}
}
}, },
trailingContent = { trailingContent = {
PriceBadge( PriceBadge(
...@@ -147,4 +83,3 @@ fun TransactionHistoryItem( ...@@ -147,4 +83,3 @@ fun TransactionHistoryItem(
modifier = modifier, modifier = modifier,
) )
} }
/*
* The MIT License (MIT)
*
* Copyright (c) 2013-2025 Chaosdorf e.V.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.chaosdorf.meteroid.ui.history
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AttachMoney
import androidx.compose.material.icons.filled.QuestionMark
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp
import coil3.compose.rememberAsyncImagePainter
import de.chaosdorf.meteroid.model.Drink
import de.chaosdorf.meteroid.theme.secondaryGradient
@Composable
fun TransactionIcon(
drink: Drink?,
deposit: Boolean,
) {
Box(
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
.aspectRatio(1.0f)
.background(MaterialTheme.colorScheme.secondaryGradient.verticalGradient())
) {
if (drink != null) {
val thumbPainter = rememberAsyncImagePainter(
drink.logoUrl,
)
val originalPainter = rememberAsyncImagePainter(
drink.originalLogoUrl,
error = thumbPainter,
)
Image(
painter = originalPainter,
contentDescription = null,
contentScale = ContentScale.Companion.Fit,
modifier = Modifier
.align(Alignment.Companion.Center)
.fillMaxSize()
)
} else {
Icon(
if (deposit) Icons.Default.AttachMoney else Icons.Default.QuestionMark,
contentDescription = null,
modifier = Modifier.align(Alignment.Companion.Center)
)
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment