package com.craigvg.lichun_android.ui.screens.dating.components import androidx.compose.animation.core.* import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Favorite import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.craigvg.lichun_android.domain.models.Person import com.craigvg.lichun_android.ui.theme.AppColors import com.craigvg.lichun_android.ui.theme.AppSpacing import com.craigvg.lichun_android.ui.theme.AppTypography import kotlinx.coroutines.delay /** * Match explanation data */ data class MatchExplanation( val matchedPersonName: String, val compatibilityScore: Int, val reasons: List ) { companion object { fun generate(person: Person, currentPersonInterests: List): MatchExplanation { val reasons = mutableListOf() if (person.compatibilityScore > 0) { reasons.add("${person.compatibilityScore}% compatible") } val shared = person.interests.count { interest -> currentPersonInterests.any { it.equals(interest, ignoreCase = true) } } if (shared > 0) { reasons.add("$shared shared interest${if (shared == 1) "" else "s"}") } if (person.ageYears in 20..35) { reasons.add("Similar age and life stage") } if (person.intelligence > 70) { reasons.add("Highly intelligent") } if (person.happiness > 80) { reasons.add("Very happy person") } if (person.occupation.isNotEmpty()) { reasons.add("Stable career") } if (reasons.isEmpty()) { reasons.add("Good match potential") } return MatchExplanation( matchedPersonName = person.firstname, compatibilityScore = person.compatibilityScore, reasons = reasons.take(3) ) } } } /** * Auto-dismissing toast showing match reasons * Ported from iOS MatchExplanationToast.swift */ @Composable fun MatchExplanationToast( explanation: MatchExplanation, onDismiss: () -> Unit ) { var isVisible by remember { mutableStateOf(false) } val offsetY by animateIntAsState( targetValue = if (isVisible) 0 else -150, animationSpec = spring( dampingRatio = Spring.DampingRatioMediumBouncy, stiffness = Spring.StiffnessMedium ), label = "toastOffset" ) val alpha by animateFloatAsState( targetValue = if (isVisible) 1f else 0f, animationSpec = spring( dampingRatio = Spring.DampingRatioMediumBouncy, stiffness = Spring.StiffnessMedium ), label = "toastAlpha" ) LaunchedEffect(Unit) { isVisible = true delay(4000) isVisible = false delay(300) onDismiss() } Box( modifier = Modifier .fillMaxWidth() .offset { IntOffset(0, offsetY) } .padding(horizontal = AppSpacing.md, vertical = AppSpacing.md) .clickable { isVisible = false } ) { Row( modifier = Modifier .fillMaxWidth() .shadow(12.dp, RoundedCornerShape(AppSpacing.largeCornerRadius)) .clip(RoundedCornerShape(AppSpacing.largeCornerRadius)) .background( Brush.linearGradient( colors = listOf(AppColors.surfaceElevated, AppColors.background) ) ) .padding(AppSpacing.md), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(AppSpacing.sm) ) { // Heart icon with glow Box( modifier = Modifier .size(48.dp) .clip(CircleShape) .background(AppColors.primary.copy(alpha = 0.15f)), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Favorite, contentDescription = null, tint = AppColors.primary, modifier = Modifier.size(AppSpacing.iconLarge) ) } Column(modifier = Modifier.weight(1f)) { Text( text = "Great Match!", style = AppTypography.headline, color = AppColors.primaryText ) Spacer(modifier = Modifier.height(2.dp)) Text( text = explanation.reasons.joinToString(" • "), style = AppTypography.caption, color = AppColors.secondaryText, maxLines = 2 ) } IconButton( onClick = { isVisible = false }, modifier = Modifier.size(24.dp) ) { Icon( imageVector = Icons.Default.Close, contentDescription = "Dismiss", tint = AppColors.secondaryText.copy(alpha = 0.6f), modifier = Modifier.size(20.dp) ) } } } }