Coverage Summary for Class: TransactionDetailsSplitCardKt (com.georgeci.moneysurfer.feature.transaction.details)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| TransactionDetailsSplitCardKt |
100%
(1/1)
|
100%
(4/4)
|
69.2%
(18/26)
|
100%
(67/67)
|
98.5%
(728/739)
|
package com.georgeci.moneysurfer.feature.transaction.details
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.georgeci.moneysurfer.uikit.theme.AppTheme
import moneysurfer.feature.transaction.generated.resources.Res
import moneysurfer.feature.transaction.generated.resources.transaction_details_split_title
import moneysurfer.feature.transaction.generated.resources.transaction_details_split_total
import moneysurfer.feature.transaction.generated.resources.transaction_details_split_uncategorized
import org.jetbrains.compose.resources.stringResource
/**
* The receipt this transaction is one leg of, broken down by category.
*
* Rendered only for a real group (see `TransactionDetailsViewModel.resolveSplit`), and it is the
* only place the whole receipt's figure appears: the hero above deliberately keeps showing the leg
* the screen was opened on, because that is the row every category analytic counted. The leg on
* screen is marked so the reader can tell which slice they arrived at.
*/
@Composable
internal fun SplitCard(split: SplitBreakdown) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.padding(bottom = 16.dp),
colors = CardDefaults.cardColors(
containerColor = AppTheme.materialColors.surfaceContainerHigh,
contentColor = AppTheme.materialColors.onSurface,
),
shape = RoundedCornerShape(20.dp),
) {
Column(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
verticalArrangement = Arrangement.spacedBy(AppTheme.spacing.small),
) {
Text(
text = stringResource(Res.string.transaction_details_split_title, split.legs.size),
style = AppTheme.typography.bodySmall,
color = AppTheme.materialColors.onSurfaceVariant,
)
val uncategorized = stringResource(Res.string.transaction_details_split_uncategorized)
split.legs.forEach { leg ->
SplitLegRow(leg = leg, fallbackCategoryName = uncategorized)
}
HorizontalDivider(color = AppTheme.materialColors.outlineVariant)
SplitTotalRow(formattedTotal = split.formattedTotal)
}
}
}
@Composable
private fun SplitLegRow(leg: SplitLegUi, fallbackCategoryName: String) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(AppTheme.spacing.small),
) {
Text(
text = leg.categoryName.ifBlank { fallbackCategoryName },
style = AppTheme.typography.bodyLarge,
// The leg the screen is showing is the one the reader navigated to; the siblings are
// context around it, so only it carries full emphasis.
color = if (leg.isCurrent) {
AppTheme.materialColors.onSurface
} else {
AppTheme.materialColors.onSurfaceVariant
},
fontWeight = if (leg.isCurrent) FontWeight.SemiBold else null,
modifier = Modifier.weight(1f),
)
Text(
text = leg.formattedAmount,
style = AppTheme.typography.bodyLarge,
color = if (leg.isCurrent) {
AppTheme.materialColors.onSurface
} else {
AppTheme.materialColors.onSurfaceVariant
},
fontWeight = if (leg.isCurrent) FontWeight.SemiBold else null,
)
}
}
@Composable
private fun SplitTotalRow(formattedTotal: String) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(AppTheme.spacing.small),
) {
Text(
text = stringResource(Res.string.transaction_details_split_total),
style = AppTheme.typography.bodySmall,
color = AppTheme.materialColors.onSurfaceVariant,
modifier = Modifier.weight(1f),
)
Text(
text = formattedTotal,
style = AppTheme.typography.bodyLarge,
color = AppTheme.materialColors.onSurface,
fontWeight = FontWeight.SemiBold,
)
}
}