Coverage Summary for Class: SurferGoalCardKt (com.georgeci.moneysurfer.uikit.components.goal)

Class Class, % Method, % Branch, % Line, % Instruction, %
SurferGoalCardKt 100% (1/1) 66.7% (2/3) 41.7% (15/36) 100% (51/51) 82.1% (271/330)


 package com.georgeci.moneysurfer.uikit.components.goal
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.georgeci.moneysurfer.uikit.atom.SurferCard
 import com.georgeci.moneysurfer.uikit.preview.SurferComponentPreview
 import com.georgeci.moneysurfer.uikit.theme.AppTheme
 
 /**
  * List card for one savings goal: emoji tile, title, status pill, progress bar and the
  * saved / target line. A PAUSED or ARCHIVED goal is dimmed so a scan of the list reads
  * "these are not moving" without any extra copy.
  */
 @Suppress("LongParameterList")
 @Composable
 fun SurferGoalCard(
     title: String,
     emoji: String,
     hue: Int,
     status: SurferGoalStatus,
     statusLabel: String,
     progress: Float,
     savedLabel: String,
     targetLabel: String,
     percentLabel: String,
     modifier: Modifier = Modifier,
     caption: String? = null,
     onClick: (() -> Unit)? = null,
 ) {
     val dimmed = status == SurferGoalStatus.Paused || status == SurferGoalStatus.Archived
     SurferCard(
         modifier = modifier.fillMaxWidth().alpha(if (dimmed) DIMMED_ALPHA else 1f),
         onClick = onClick,
     ) {
         Column(
             modifier = Modifier.padding(AppTheme.spacing.default),
             verticalArrangement = Arrangement.spacedBy(AppTheme.spacing.medium),
         ) {
             Row(
                 verticalAlignment = Alignment.CenterVertically,
                 horizontalArrangement = Arrangement.spacedBy(AppTheme.spacing.medium),
             ) {
                 SurferGoalIcon(emoji = emoji, hue = hue)
                 Column(modifier = Modifier.weight(1f)) {
                     Text(
                         text = title,
                         style = AppTheme.typography.titleMedium.copy(fontWeight = FontWeight.Medium),
                         color = AppTheme.materialColors.onSurface,
                         maxLines = 1,
                         overflow = TextOverflow.Ellipsis,
                     )
                     if (caption != null) {
                         Text(
                             text = caption,
                             style = AppTheme.typography.bodySmall,
                             color = AppTheme.materialColors.onSurfaceVariant,
                             maxLines = 1,
                             overflow = TextOverflow.Ellipsis,
                         )
                     }
                 }
                 Spacer(Modifier.width(AppTheme.spacing.small))
                 SurferGoalStatusPill(status = status, label = statusLabel)
             }
 
             SurferGoalProgressBar(progress = progress, color = goalAccentColor(hue))
 
             Row(
                 modifier = Modifier.fillMaxWidth(),
                 verticalAlignment = Alignment.CenterVertically,
                 horizontalArrangement = Arrangement.SpaceBetween,
             ) {
                 Text(
                     text = "$savedLabel / $targetLabel",
                     style = AppTheme.typography.bodyMedium,
                     color = AppTheme.materialColors.onSurface,
                 )
                 Text(
                     text = percentLabel,
                     style = AppTheme.typography.labelLarge,
                     color = AppTheme.materialColors.onSurfaceVariant,
                 )
             }
         }
     }
 }
 
 private const val DIMMED_ALPHA = 0.7f
 
 @Preview
 @Composable
 private fun SurferGoalCardPreview() {
     SurferComponentPreview {
         Column(
             modifier = Modifier.padding(16.dp),
             verticalArrangement = Arrangement.spacedBy(12.dp),
         ) {
             SurferGoalCard(
                 title = "Emergency fund",
                 emoji = "☂️",
                 hue = 210,
                 status = SurferGoalStatus.Active,
                 statusLabel = "Active",
                 progress = 0.74f,
                 savedLabel = "€8,915",
                 targetLabel = "€12,000",
                 percentLabel = "74%",
                 caption = "by Aug 2026",
             )
             SurferGoalCard(
                 title = "Lisbon trip",
                 emoji = "🏖️",
                 hue = 30,
                 status = SurferGoalStatus.Paused,
                 statusLabel = "Paused",
                 progress = 0.62f,
                 savedLabel = "€1,480",
                 targetLabel = "€2,400",
                 percentLabel = "62%",
             )
         }
     }
 }