Coverage Summary for Class: DashboardSafeToSpendWidgetKt (com.georgeci.moneysurfer.feature.dashboard)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| DashboardSafeToSpendWidgetKt |
100%
(3/3)
|
60%
(9/15)
|
100%
(38/38)
|
98%
(339/346)
|
| DashboardSafeToSpendWidgetKt$WhenMappings |
|
| Total |
100%
(3/3)
|
60%
(9/15)
|
100%
(38/38)
|
98%
(339/346)
|
package com.georgeci.moneysurfer.feature.dashboard
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import com.georgeci.moneysurfer.domain.model.BudgetStatus
import com.georgeci.moneysurfer.uikit.components.budget.SurferBudgetStatus
import com.georgeci.moneysurfer.uikit.widgets.SurferSafeToSpendData
import com.georgeci.moneysurfer.uikit.widgets.SurferSafeToSpendEmpty
import com.georgeci.moneysurfer.uikit.widgets.SurferSafeToSpendWidget
import moneysurfer.feature.dashboard.generated.resources.Res
import moneysurfer.feature.dashboard.generated.resources.dashboard_days_left
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_bar_a11y
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_caption
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_empty_subtitle
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_empty_title
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_over_caption
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_per_day
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_set_budget
import moneysurfer.feature.dashboard.generated.resources.dashboard_safe_to_spend_title
import org.jetbrains.compose.resources.pluralStringResource
import org.jetbrains.compose.resources.stringResource
/**
* What is still safe to spend this period, and the pace that makes it last.
*
* Unlike the quick-actions row this one keeps drawing with nothing behind it: "no budget" is a
* state the widget is *for*, and the card that says so also carries the link that fixes it.
*/
@Composable
internal fun SafeToSpendWidget(
state: DashboardState.Content,
onEvent: (DashboardEvent) -> Unit,
) {
SurferSafeToSpendWidget(
title = stringResource(Res.string.dashboard_safe_to_spend_title),
data = state.safeToSpend?.toWidgetData(),
empty = SurferSafeToSpendEmpty(
title = stringResource(Res.string.dashboard_safe_to_spend_empty_title),
subtitle = stringResource(Res.string.dashboard_safe_to_spend_empty_subtitle),
actionLabel = stringResource(Res.string.dashboard_safe_to_spend_set_budget),
onActionClick = { onEvent(DashboardEvent.OnSetBudgetClick) },
actionTestTag = DashboardTestTags.SafeToSpendSetBudget,
),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.padding(vertical = 8.dp)
.testTag(DashboardTestTags.SafeToSpend),
)
}
/**
* The sentences around the numbers. The bar restates figures the card already prints, so its
* screen-reader line is the spend against the limit rather than a percentage read off the shape.
*/
@Composable
private fun SafeToSpendUi.toWidgetData(): SurferSafeToSpendData {
val daysLeftLabel = pluralStringResource(Res.plurals.dashboard_days_left, daysLeft, daysLeft)
val captionResource = if (isOver) {
Res.string.dashboard_safe_to_spend_over_caption
} else {
Res.string.dashboard_safe_to_spend_caption
}
return SurferSafeToSpendData(
amount = remainingFormatted,
caption = stringResource(captionResource, limitFormatted, budgetName),
perDay = stringResource(Res.string.dashboard_safe_to_spend_per_day, perDayFormatted),
daysLeft = daysLeftLabel,
progress = progress,
paceFraction = paceFraction,
status = status.toWidgetStatus(),
progressContentDescription = stringResource(
Res.string.dashboard_safe_to_spend_bar_a11y,
spentFormatted,
limitFormatted,
daysLeftLabel,
),
)
}
/** `uikit` does not depend on `domain`, so the status word crosses over here. */
internal fun BudgetStatus.toWidgetStatus(): SurferBudgetStatus = when (this) {
BudgetStatus.OK -> SurferBudgetStatus.Ok
BudgetStatus.WARN -> SurferBudgetStatus.Warn
BudgetStatus.OVER -> SurferBudgetStatus.Over
}