@ -7,6 +7,11 @@ import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.border
@ -18,17 +23,15 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.TextSnippet
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.ChatBubble
import androidx.compose.material.icons.filled.ChatBubble
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FlashO n
import androidx.compose.material.icons.filled.KeyboardArrowDow n
import androidx.compose.material.icons.filled.Mood
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material.icons.filled.MoreHoriz
import androidx.compose.material.icons.filled.MoreHoriz
import androidx.compose.material.icons.filled.MusicNote
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.filled.TextSnippet
import androidx.compose.material.icons.outlined.LocationOn
import androidx.compose.material3.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.saveable.rememberSaveable
@ -48,18 +51,12 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage
import coil.compose.AsyncImage
import com.example.dattingapp.homes.networkandapi.*
import com.example.dattingapp.homes.networkandapi.*
import com.example.dattingapp.homes.profile.FrienPostMedia
import com.example.dattingapp.homes.profile.FriendAuthor
import com.example.dattingapp.homes.profile.FriendPost
import com.example.dattingapp.homes.profile.FriendPost
import com.example.dattingapp.homes.profile.FriendProfileResponse
import com.example.dattingapp.homes.profile.FriendProfileResponse
import com.example.dattingapp.homes.profile.LikedUserResponse
import com.example.dattingapp.ui.theme.*
import com.example.dattingapp.ui.theme.*
import java.time.LocalDate
import java.time.LocalDate
import java.time.Period
import java.time.Period
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatter
import kotlin.jvm.java
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
class FriendProfile : ComponentActivity ( ) {
class FriendProfile : ComponentActivity ( ) {
override fun onCreate ( savedInstanceState : Bundle ? ) {
override fun onCreate ( savedInstanceState : Bundle ? ) {
@ -126,9 +123,9 @@ fun FriendProfileScreen(
val matchesViewModel : MatchesViewModel = viewModel ( )
val matchesViewModel : MatchesViewModel = viewModel ( )
// Collect response states
// Collect response states
val likesState by likedViewModel . likesUiState . collectAsState ( ) // Users who liked me
val likesState by likedViewModel . likesUiState . collectAsState ( )
val likedState by likedViewModel . likedUiState . collectAsState ( ) // Users I liked
val likedState by likedViewModel . likedUiState . collectAsState ( )
val matchesState by matchesViewModel . state . collectAsState ( ) // Match list from server
val matchesState by matchesViewModel . state . collectAsState ( )
// Fetch lists once
// Fetch lists once
LaunchedEffect ( Unit ) {
LaunchedEffect ( Unit ) {
@ -154,16 +151,12 @@ fun FriendProfileScreen(
// Track local tap in current screen session
// Track local tap in current screen session
var localLiked by rememberSaveable { mutableStateOf ( false ) }
var localLiked by rememberSaveable { mutableStateOf ( false ) }
// =========================================================================
// Toggle state for extra profile details (hidden by default, persists across state changes)
var showExtraInfo by rememberSaveable { mutableStateOf ( false ) }
// 2-STEP MATCH EVALUATION LOGIC
// 2-STEP MATCH EVALUATION LOGIC
// =========================================================================
// STEP 1: Check online match list first
val isOnlineMatch = friendProfileData . id in matchIds
val isOnlineMatch = friendProfileData . id in matchIds
// STEP 2: If NOT an online match, check if he liked me + local like action
val isLocalMatch = !is OnlineMatch && heLikedMe && localLiked
val isLocalMatch = !is OnlineMatch && heLikedMe && localLiked
// Final match decision
val isMatched = isOnlineMatch || isLocalMatch
val isMatched = isOnlineMatch || isLocalMatch
// Derived button flags
// Derived button flags
@ -175,176 +168,174 @@ fun FriendProfileScreen(
calculateAge ( friendProfileData . birth_date )
calculateAge ( friendProfileData . birth_date )
}
}
val scrollState = rememberScrollState ( )
Column (
Column (
modifier = Modifier
modifier = Modifier
. fillMaxSize ( )
. fillMaxSize ( )
. background ( Color . White )
. background ( Color . White )
. verticalScroll ( rememberScrollState ( ) )
. verticalScroll ( scrollState )
. padding ( 16. dp )
) {
) {
// Header Cover & Profile Avatar
// ====================================================
Box (
// 1. HEADER: Active Now & Action Icons
modifier = Modifier
// ====================================================
. fillMaxWidth ( )
. height ( 250. dp )
) {
Image (
painter = painterResource ( id = R . drawable . gallarypermissionbg ) ,
contentDescription = " cover photo " ,
modifier = Modifier
. fillMaxWidth ( )
. height ( 200. dp )
. clip ( RoundedCornerShape ( bottomStart = 10. dp , bottomEnd = 20. dp ) ) ,
contentScale = ContentScale . Crop
)
Row (
Row (
modifier = Modifier
modifier = Modifier . fillMaxWidth ( ) ,
. fillMaxWidth ( )
. padding ( horizontal = 16. dp , vertical = 25. dp ) ,
horizontalArrangement = Arrangement . SpaceBetween ,
horizontalArrangement = Arrangement . SpaceBetween ,
verticalAlignment = Alignment . CenterVertically
verticalAlignment = Alignment . CenterVertically
) {
) {
Surface (
shape = RoundedCornerShape ( 16. dp ) ,
color = Color ( 0xFFF2EBF9 )
) {
Row (
modifier = Modifier . padding ( horizontal = 10. dp , vertical = 6. dp ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 6. dp )
) {
Box (
modifier = Modifier
. size ( 8. dp )
. clip ( CircleShape )
. background ( BrandMagenta )
)
Text (
text = " Active now " ,
fontSize = 12. sp ,
fontWeight = FontWeight . Bold ,
color = BrandMagenta
)
}
}
Row ( horizontalArrangement = Arrangement . spacedBy ( 8. dp ) ) {
IconButton (
IconButton (
onClick = onBackClick ,
onClick = onBackClick ,
modifier = Modifier . size ( 20. dp ) . clip ( CircleShape )
modifier = Modifier
. size ( 36. dp )
. clip ( CircleShape )
. background ( Color ( 0xFFF7F7F7 ) )
) {
) {
Icon (
Icon (
imageVector = Icons . AutoMirrored . Filled . ArrowBack ,
imageVector = Icons . AutoMirrored . Filled . ArrowBack ,
contentDescription = " back button "
contentDescription = " Back " ,
tint = textDark ,
modifier = Modifier . size ( 18. dp )
)
)
}
}
IconButton (
IconButton (
onClick = onMoreClick ,
onClick = onMoreClick ,
modifier = Modifier . size ( 20. dp ) . clip ( CircleShape )
modifier = Modifier
. size ( 36. dp )
. clip ( CircleShape )
. background ( Color ( 0xFFF7F7F7 ) )
) {
) {
Icon (
Icon (
imageVector = Icons . Default . MoreHoriz ,
imageVector = Icons . Default . MoreHoriz ,
contentDescription = " more options "
contentDescription = " More Options " ,
tint = textDark ,
modifier = Modifier . size ( 18. dp )
)
)
}
}
}
}
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
// ====================================================
// 2. PROFILE IDENTITY
// ====================================================
Row (
modifier = Modifier . fillMaxWidth ( ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 16. dp )
) {
Box (
modifier = Modifier
. size ( 84. dp )
. clip ( CircleShape )
. background ( brush = Brush . linearGradient ( colors = listOf ( BrandMagenta , BrandPurple ) ) )
. padding ( 3. dp )
) {
AsyncImage (
AsyncImage (
model = friendProfileData . profile_image_url ,
model = friendProfileData . profile_image_url ?: " https://picsum.photos/300/300 " ,
contentDescription = " Profile Avatar " ,
contentDescription = " Profile Picture " ,
contentScale = ContentScale . Crop ,
placeholder = painterResource ( id = R . drawable . locationpermissionbg ) ,
placeholder = painterResource ( id = R . drawable . locationpermissionbg ) ,
error = painterResource ( id = R . drawable . locationpermissionbg ) ,
error = painterResource ( id = R . drawable . locationpermissionbg ) ,
modifier = Modifier
modifier = Modifier
. padding ( start = 20. dp )
. fillMaxSize ( )
. align ( Alignment . BottomStart )
. size ( 100. dp )
. clip ( CircleShape )
. clip ( CircleShape )
. border ( 4. dp , Color . White , CircleShape ) ,
contentScale = ContentScale . Crop
)
)
}
}
Spacer ( modifier = Modifier . height ( 12. dp ) )
Column ( verticalArrangement = Arrangement . spacedBy ( 4. dp ) ) {
// Profile Main Details
Column (
modifier = Modifier
. fillMaxWidth ( )
. padding ( horizontal = 20. dp )
) {
Row (
Row (
verticalAlignment = Alignment . CenterVertically ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 8 .dp )
horizontalArrangement = Arrangement . spacedBy ( 6. dp )
) {
) {
val displayName = friendProfileData . full_name ?: " User "
val displayName = friendProfileData . full_name ?: " Alex Rivera "
val nameAndAge = if ( age != null ) " $displayName , $age " else displayName
Text (
Text (
text = nameAndAg e,
text = displayName ,
fontSize = 24 . sp ,
fontSize = 20 . sp ,
fontWeight = FontWeight . Bold ,
fontWeight = FontWeight . Bold ,
color = textDark
color = textDark
)
)
Surface (
if ( age != null ) {
shape = RoundedCornerShape ( 12. dp ) ,
color = BadgePink
) {
Row (
modifier = Modifier . padding ( horizontal = 8. dp , vertical = 3. dp ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 4. dp )
) {
Icon (
imageVector = Icons . Default . Favorite ,
contentDescription = null ,
tint = Color . White ,
modifier = Modifier . size ( 10. dp )
)
Text (
Text (
text = " ${friendProfileData.county ?: 0} % Match " ,
text = " $age " ,
color = Color . White ,
fontSize = 20. sp ,
fontSize = 10. sp ,
fontWeight = FontWeight . Normal ,
fontWeight = FontWeight . Bold
color = textDark
)
)
}
}
}
}
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 4. dp ) ,
modifier = Modifier . padding ( vertical = 4. dp )
) {
Icon (
Icon (
imageVector = Icons . Outlined . LocationOn ,
imageVector = Icons . Default . Check ,
contentDescription = null ,
contentDescription = " Verified " ,
tint = Color . Gray ,
tint = BrandMagenta ,
modifier = Modifier . size ( 14. dp )
modifier = Modifier . size ( 16. dp )
)
Text (
text = " ${friendProfileData.city ?: "Unknown"} , ${friendProfileData.country ?: ""} " ,
fontSize = 12. sp ,
color = Color . Gray
)
)
}
}
Surface (
val city = friendProfileData . city ?: " New York "
modifier = Modifier
. fillMaxWidth ( )
. padding ( vertical = 8. dp ) ,
shape = RoundedCornerShape ( 12. dp ) ,
color = Color ( 0xFFF9F9F9 ) ,
shadowElevation = 1. dp
) {
Text (
Text (
text = friendProfileData . bio ?: " " ,
text = " 📍 $city , NY • 2 miles away " ,
fontSize = 13. sp ,
fontSize = 12. sp ,
color = Color ( 0xFF4A4A4A ) ,
color = BrandPurple ,
modifier = Modifier . padding ( 12. dp ) ,
fontWeight = FontWeight . SemiBold
maxLines = 2 ,
lineHeight = 18. sp
)
)
}
}
}
// =========================================================================
Spacer ( modifier = Modifier . height ( 16. dp ) )
// ACTION BUTTON ROW WITH EVALUATED MATCH STATES
// =========================================================================
// ====================================================
// 3. ACTION BUTTON ROW (Message, Like, Super Like, Dislike)
// ====================================================
Row (
Row (
modifier = Modifier
modifier = Modifier
. fillMaxWidth ( )
. fillMaxWidth ( )
. padding ( vertical = 8 .dp ) ,
. padding ( vertical = 4 .dp ) ,
horizontalArrangement = Arrangement . spacedBy ( 10 .dp ) ,
horizontalArrangement = Arrangement . spacedBy ( 8 .dp ) ,
verticalAlignment = Alignment . CenterVertically
verticalAlignment = Alignment . CenterVertically
) {
) {
// 💬 Message Button — Enabled ONLY when matched
// 💬 Message Button
Card (
Card (
onClick = onMessageClick ,
onClick = onMessageClick ,
enabled = isMessageClickable ,
enabled = isMessageClickable ,
modifier = Modifier
modifier = Modifier
. weight ( 1f )
. weight ( 1f )
. height ( 48. dp ) ,
. height ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors (
colors = CardDefaults . cardColors (
containerColor = if ( isMessageClickable ) Color . White else Color ( 0xFFF0F0F0 ) ,
containerColor = if ( isMessageClickable ) Color . White else Color ( 0xFFF0F0F0 ) ,
disabledContainerColor = Color ( 0xFFF0F0F0 )
disabledContainerColor = Color ( 0xFFF0F0F0 )
) ,
) ,
elevation = CardDefaults . cardElevation (
elevation = CardDefaults . cardElevation (
defaultElevation = if ( isMessageClickable ) 4. dp else 0. dp
defaultElevation = if ( isMessageClickable ) 2. dp else 0. dp
)
) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
) {
Row (
Row (
modifier = Modifier . fillMaxSize ( ) ,
modifier = Modifier . fillMaxSize ( ) ,
@ -355,12 +346,12 @@ fun FriendProfileScreen(
imageVector = Icons . Default . ChatBubble ,
imageVector = Icons . Default . ChatBubble ,
contentDescription = " Message " ,
contentDescription = " Message " ,
tint = if ( isMessageClickable ) textDark else Color ( 0xFFBDBDBD ) ,
tint = if ( isMessageClickable ) textDark else Color ( 0xFFBDBDBD ) ,
modifier = Modifier . size ( 18 . dp )
modifier = Modifier . size ( 16 . dp )
)
)
Spacer ( modifier = Modifier . width ( 8 .dp ) )
Spacer ( modifier = Modifier . width ( 6 .dp ) )
Text (
Text (
text = " Message " ,
text = " Message " ,
fontSize = 16 . sp ,
fontSize = 14 . sp ,
fontWeight = FontWeight . Bold ,
fontWeight = FontWeight . Bold ,
color = if ( isMessageClickable ) textDark else Color ( 0xFFBDBDBD )
color = if ( isMessageClickable ) textDark else Color ( 0xFFBDBDBD )
)
)
@ -369,7 +360,6 @@ fun FriendProfileScreen(
// ❤️ Like & ⭐ Super Like Buttons — Hidden when matched
// ❤️ Like & ⭐ Super Like Buttons — Hidden when matched
if ( showLikeAndSuperLike ) {
if ( showLikeAndSuperLike ) {
// ❤️ Like Button
Card (
Card (
onClick = {
onClick = {
onLikeClick ( )
onLikeClick ( )
@ -379,14 +369,15 @@ fun FriendProfileScreen(
} ,
} ,
enabled = ! likeDisabled ,
enabled = ! likeDisabled ,
modifier = Modifier . size ( 48. dp ) ,
modifier = Modifier . size ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors (
colors = CardDefaults . cardColors (
containerColor = if ( heLikedMe ) Color ( 0xFFE53935 ) else Color . White ,
containerColor = if ( heLikedMe ) Color ( 0xFFE53935 ) else Color . White ,
disabledContainerColor = if ( heLikedMe ) Color ( 0xFFE53935 ) else Color ( 0xFFF0F0F0 )
disabledContainerColor = if ( heLikedMe ) Color ( 0xFFE53935 ) else Color ( 0xFFF0F0F0 )
) ,
) ,
elevation = CardDefaults . cardElevation (
elevation = CardDefaults . cardElevation (
defaultElevation = if ( likeDisabled ) 0. dp else 2. dp
defaultElevation = if ( likeDisabled ) 0. dp else 2. dp
)
) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Icon (
Icon (
@ -402,7 +393,6 @@ fun FriendProfileScreen(
}
}
}
}
// ⭐ Super Like (Star) Button
Card (
Card (
onClick = {
onClick = {
onStarClick ( )
onStarClick ( )
@ -412,14 +402,15 @@ fun FriendProfileScreen(
} ,
} ,
enabled = ! likeDisabled ,
enabled = ! likeDisabled ,
modifier = Modifier . size ( 48. dp ) ,
modifier = Modifier . size ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors (
colors = CardDefaults . cardColors (
containerColor = Color . White ,
containerColor = Color . White ,
disabledContainerColor = Color ( 0xFFF0F0F0 )
disabledContainerColor = Color ( 0xFFF0F0F0 )
) ,
) ,
elevation = CardDefaults . cardElevation (
elevation = CardDefaults . cardElevation (
defaultElevation = if ( likeDisabled ) 0. dp else 2. dp
defaultElevation = if ( likeDisabled ) 0. dp else 2. dp
)
) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Icon (
Icon (
@ -432,21 +423,21 @@ fun FriendProfileScreen(
}
}
}
}
// ❌ Cancel / Dislike Button — Resets everything back to initial state
// ❌ Dislike / Cancel Button
Card (
Card (
onClick = {
onClick = {
onCancelClick ( )
onCancelClick ( )
handleLikeAndDislikeAction ( context , " pass " , friendProfileData , swipeViewModel )
handleLikeAndDislikeAction ( context , " pass " , friendProfileData , swipeViewModel )
localLiked = false
localLiked = false
likedViewModel . likedResponse ( context , " Likes " )
likedViewModel . likedResponse ( context , " Likes " )
likedViewModel . likedResponse ( context , " Liked " )
likedViewModel . likedResponse ( context , " Liked " )
matchesViewModel . loadMatches ( context )
matchesViewModel . loadMatches ( context )
} ,
} ,
modifier = Modifier . size ( 48. dp ) ,
modifier = Modifier . size ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors ( containerColor = Color . White ) ,
colors = CardDefaults . cardColors ( containerColor = Color . White ) ,
elevation = CardDefaults . cardElevation ( defaultElevation = 2. dp )
elevation = CardDefaults . cardElevation ( defaultElevation = 2. dp ) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Icon (
Icon (
@ -459,20 +450,359 @@ fun FriendProfileScreen(
}
}
}
}
Spacer ( modifier = Modifier . height ( 12. dp ) )
// ====================================================
// 4. LOOKING FOR CARD (ALWAYS VISIBLE)
// ====================================================
Card (
modifier = Modifier . fillMaxWidth ( ) ,
shape = RoundedCornerShape ( 14. dp ) ,
colors = CardDefaults . cardColors ( containerColor = Color ( 0xFFF7F4F9 ) ) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
Row (
modifier = Modifier
. fillMaxWidth ( )
. padding ( 14. dp ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . SpaceBetween
) {
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 10. dp )
) {
Box (
modifier = Modifier
. size ( 32. dp )
. clip ( CircleShape )
. background ( BrandMagenta . copy ( alpha = 0.15f ) ) ,
contentAlignment = Alignment . Center
) {
Icon (
imageVector = Icons . Default . Favorite ,
contentDescription = null ,
tint = BrandMagenta ,
modifier = Modifier . size ( 16. dp )
)
}
Column {
Text (
text = " LOOKING FOR " ,
fontSize = 10. sp ,
fontWeight = FontWeight . Bold ,
color = TextMuted
)
Text (
text = " Long-term relationship / Serious dating " ,
fontSize = 13. sp ,
fontWeight = FontWeight . Bold ,
color = textDark
)
}
}
Text ( text = " › " , fontSize = 18. sp , color = TextMuted )
}
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
Spacer ( modifier = Modifier . height ( 16. dp ) )
// User Posts Section
// ====================================================
// 5. VIDEO INTRO (ALWAYS VISIBLE)
// ====================================================
Column ( modifier = Modifier . fillMaxWidth ( ) ) {
Row (
modifier = Modifier . fillMaxWidth ( ) ,
horizontalArrangement = Arrangement . SpaceBetween ,
verticalAlignment = Alignment . CenterVertically
) {
Row ( verticalAlignment = Alignment . CenterVertically , horizontalArrangement = Arrangement . spacedBy ( 6. dp ) ) {
Icon ( imageVector = Icons . Default . PlayArrow , contentDescription = null , tint = BrandMagenta , modifier = Modifier . size ( 18. dp ) )
Text ( text = " Video Intro " , fontSize = 15. sp , fontWeight = FontWeight . Bold , color = textDark )
}
Surface (
shape = RoundedCornerShape ( 12. dp ) ,
color = Color ( 0xFFF2EBF9 )
) {
Text (
text = " Say hello! 📹 " ,
fontSize = 11. sp ,
color = BrandMagenta ,
fontWeight = FontWeight . Bold ,
modifier = Modifier . padding ( horizontal = 8. dp , vertical = 4. dp )
)
}
}
Spacer ( modifier = Modifier . height ( 8. dp ) )
Box (
modifier = Modifier
. fillMaxWidth ( )
. height ( 200. dp )
. clip ( RoundedCornerShape ( 16. dp ) )
. background ( Color . Black )
) {
AsyncImage (
model = " https://picsum.photos/600/300 " ,
contentDescription = " Video Intro " ,
contentScale = ContentScale . Crop ,
modifier = Modifier . fillMaxSize ( )
)
Box (
modifier = Modifier
. size ( 48. dp )
. clip ( CircleShape )
. background ( Color . White . copy ( alpha = 0.9f ) )
. align ( Alignment . Center ) ,
contentAlignment = Alignment . Center
) {
Icon ( imageVector = Icons . Default . PlayArrow , contentDescription = " Play " , tint = BrandMagenta , modifier = Modifier . size ( 28. dp ) )
}
Surface (
color = Color . Black . copy ( alpha = 0.6f ) ,
shape = RoundedCornerShape ( 8. dp ) ,
modifier = Modifier
. align ( Alignment . BottomStart )
. padding ( 10. dp )
) {
Text (
text = " 0:45s \" Quick vibe & Sunday routine \" " ,
color = Color . White ,
fontSize = 10. sp ,
modifier = Modifier . padding ( horizontal = 8. dp , vertical = 4. dp )
)
}
}
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
// ====================================================
// 6. TOGGLE BUTTON FOR EXTRA PROFILE DETAILS
// ====================================================
Surface (
modifier = Modifier
. fillMaxWidth ( )
. clickable { showExtraInfo = ! showExtraInfo } ,
shape = RoundedCornerShape ( 12. dp ) ,
color = Color ( 0xFFF2EBF9 )
) {
Row (
modifier = Modifier . padding ( vertical = 12. dp , horizontal = 16. dp ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . SpaceBetween
) {
Text (
text = if ( showExtraInfo ) " Hide Extra Profile Details " else " View All Profile Details " ,
fontSize = 13. sp ,
fontWeight = FontWeight . Bold ,
color = BrandMagenta
)
Icon (
imageVector = if ( showExtraInfo ) Icons . Default . KeyboardArrowUp else Icons . Default . KeyboardArrowDown ,
contentDescription = " Toggle Details " ,
tint = BrandMagenta
)
}
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
// ====================================================
// 7. EXTRA PROFILE DETAILS (COLLAPSIBLE / HIDDEN BY DEFAULT)
// ====================================================
AnimatedVisibility (
visible = showExtraInfo ,
enter = expandVertically ( ) + fadeIn ( ) ,
exit = shrinkVertically ( ) + fadeOut ( )
) {
Column ( modifier = Modifier . fillMaxWidth ( ) ) {
// About Section
Text (
text = " About ${friendProfileData.full_name?.substringBefore(" ") ?: "Alex"} " ,
fontSize = 15. sp ,
fontWeight = FontWeight . Bold ,
color = textDark
)
Spacer ( modifier = Modifier . height ( 6. dp ) )
Text (
text = friendProfileData . bio ?: " Adventure seeker, dog lover, and amateur chef. Always hunting for the crispiest croissants in Brooklyn. " ,
fontSize = 13. sp ,
color = Color ( 0xFF555555 ) ,
lineHeight = 18. sp
)
Spacer ( modifier = Modifier . height ( 16. dp ) )
// Dating Prompt Card
Card (
modifier = Modifier . fillMaxWidth ( ) ,
shape = RoundedCornerShape ( 16. dp ) ,
colors = CardDefaults . cardColors ( containerColor = Color ( 0xFFF9F7FB ) ) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
Column ( modifier = Modifier . padding ( 14. dp ) ) {
Text ( text = " DATING PROMPT " , fontSize = 9. sp , fontWeight = FontWeight . Bold , color = BrandMagenta )
Spacer ( modifier = Modifier . height ( 4. dp ) )
Text ( text = " My Ideal weekend is... " , fontSize = 15. sp , fontWeight = FontWeight . Bold , color = textDark )
Spacer ( modifier = Modifier . height ( 6. dp ) )
Text ( text = " Hunting down the crispiest croissants in Brooklyn, visiting a modern art exhibit, and sunset walks by the pier. " , fontSize = 12. sp , color = Color ( 0xFF555555 ) , lineHeight = 16. sp )
}
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
// Interests & Passions
Column ( modifier = Modifier . fillMaxWidth ( ) ) {
Row (
modifier = Modifier . fillMaxWidth ( ) ,
horizontalArrangement = Arrangement . SpaceBetween ,
verticalAlignment = Alignment . CenterVertically
) {
Text (
text = " Interests & Passions " ,
fontSize = 15. sp ,
fontWeight = FontWeight . Bold ,
color = textDark
)
Text (
text = " ${friendProfileData.county ?: 8} Shared " ,
fontSize = 11. sp ,
fontWeight = FontWeight . Bold ,
color = BrandMagenta
)
}
Spacer ( modifier = Modifier . height ( 8. dp ) )
val interestsList = listOf ( " 📷 Photography " , " 🐶 Dogs " , " ☕ Coffee Culture " , " ✈️ Travel " , " 🎨 Art & Design " , " 🍷 Wine Tasting " )
OptFlowRow ( interestsList )
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
// Key Information
Column (
modifier = Modifier . fillMaxWidth ( ) ,
verticalArrangement = Arrangement . spacedBy ( 10. dp )
) {
Text (
text = " Key Information " ,
fontSize = 15. sp ,
fontWeight = FontWeight . Bold ,
color = textDark
)
InfoRow ( icon = " 💼 " , title = " Occupation " , value = " Creative Director at Studio Drift " )
InfoRow ( icon = " 🎓 " , title = " Education " , value = " NYU Gallatin School " )
InfoRow ( icon = " 📏 " , title = " Height " , value = " 5'9 \" (175 cm) " )
InfoRow ( icon = " 🏛️ " , title = " Beliefs " , value = " Spiritual / Agnostic " )
}
Spacer ( modifier = Modifier . height ( 16. dp ) )
// Lifestyle Details
Column ( modifier = Modifier . fillMaxWidth ( ) ) {
Text (
text = " Lifestyle Details " ,
fontSize = 15. sp ,
fontWeight = FontWeight . Bold ,
color = textDark
)
Spacer ( modifier = Modifier . height ( 8. dp ) )
Row ( horizontalArrangement = Arrangement . spacedBy ( 8. dp ) , modifier = Modifier . fillMaxWidth ( ) ) {
LifestyleTile ( icon = " 🚭 " , label = " Smoking " , detail = " Non-smoker " , modifier = Modifier . weight ( 1f ) )
LifestyleTile ( icon = " 🍷 " , label = " Drinking " , detail = " Socially " , modifier = Modifier . weight ( 1f ) )
}
}
Spacer ( modifier = Modifier . height ( 20. dp ) )
}
}
// ====================================================
// 8. USER POSTS / MASONRY GRID SECTION (ALWAYS VISIBLE)
// ====================================================
Text (
Text (
text = " Posts " ,
text = " Posts " ,
fontSize = 18. sp ,
fontSize = 16 . sp ,
fontWeight = FontWeight . Bold ,
fontWeight = FontWeight . Bold ,
color = textDark ,
color = textDark ,
modifier = Modifier . padding ( bottom = 8. dp )
modifier = Modifier . padding ( bottom = 8. dp )
)
)
Spacer ( modifier = Modifier . height ( 16. dp ) )
StaggeredFriendPostsGrid ( posts = friendProfileData . posts )
StaggeredFriendPostsGrid ( posts = friendProfileData . posts )
Spacer ( modifier = Modifier . height ( 30. dp ) )
}
}
// ============================================================
// HELPER COMPOSABLES
// ============================================================
@Composable
private fun InfoRow ( icon : String , title : String , value : String ) {
Row (
modifier = Modifier . fillMaxWidth ( ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 12. dp )
) {
Box (
modifier = Modifier
. size ( 32. dp )
. clip ( CircleShape )
. background ( Color ( 0xFFF5F5F5 ) ) ,
contentAlignment = Alignment . Center
) {
Text ( text = icon , fontSize = 14. sp )
}
Column {
Text ( text = title , fontSize = 10. sp , color = TextMuted )
Text ( text = value , fontSize = 12. sp , fontWeight = FontWeight . SemiBold , color = textDark )
}
}
}
@Composable
private fun LifestyleTile ( icon : String , label : String , detail : String , modifier : Modifier = Modifier ) {
Surface (
modifier = modifier ,
shape = RoundedCornerShape ( 12. dp ) ,
color = Color ( 0xFFF9F9F9 )
) {
Row (
modifier = Modifier . padding ( 10. dp ) ,
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 8. dp )
) {
Text ( text = icon , fontSize = 16. sp )
Column {
Text ( text = label , fontSize = 9. sp , color = TextMuted )
Text ( text = detail , fontSize = 11. sp , fontWeight = FontWeight . Bold , color = textDark )
}
}
}
}
@Composable
private fun OptFlowRow ( items : List < String > ) {
Column ( verticalArrangement = Arrangement . spacedBy ( 6. dp ) ) {
val chunked = items . chunked ( 3 )
chunked . forEach { rowItems ->
Row ( horizontalArrangement = Arrangement . spacedBy ( 6. dp ) ) {
rowItems . forEach { item ->
Surface (
shape = RoundedCornerShape ( 16. dp ) ,
color = Color ( 0xFFF4F4F4 )
) {
Text (
text = item ,
fontSize = 11. sp ,
fontWeight = FontWeight . Medium ,
color = textDark ,
modifier = Modifier . padding ( horizontal = 10. dp , vertical = 6. dp )
)
}
}
}
}
}
}
}
}
}
@ -495,15 +825,15 @@ fun StaggeredFriendPostsGrid(posts: List<FriendPost>) {
Row (
Row (
modifier = Modifier . fillMaxWidth ( ) ,
modifier = Modifier . fillMaxWidth ( ) ,
horizontalArrangement = Arrangement . spacedBy ( 3 .dp )
horizontalArrangement = Arrangement . spacedBy ( 6 .dp )
) {
) {
Column ( modifier = Modifier . weight ( 1f ) , verticalArrangement = Arrangement . spacedBy ( 4 .dp ) ) {
Column ( modifier = Modifier . weight ( 1f ) , verticalArrangement = Arrangement . spacedBy ( 6 .dp ) ) {
columns . first . forEachIndexed { idx , post ->
columns . first . forEachIndexed { idx , post ->
val aspectRatio = if ( idx % 2 == 0 ) 0.8f else 1.2f
val aspectRatio = if ( idx % 2 == 0 ) 0.8f else 1.2f
MasonryPostItem ( post = post , aspectRatio = aspectRatio )
MasonryPostItem ( post = post , aspectRatio = aspectRatio )
}
}
}
}
Column ( modifier = Modifier . weight ( 1f ) , verticalArrangement = Arrangement . spacedBy ( 4 .dp ) ) {
Column ( modifier = Modifier . weight ( 1f ) , verticalArrangement = Arrangement . spacedBy ( 6 .dp ) ) {
columns . second . forEachIndexed { idx , post ->
columns . second . forEachIndexed { idx , post ->
val aspectRatio = if ( idx % 2 == 0 ) 1.2f else 0.8f
val aspectRatio = if ( idx % 2 == 0 ) 1.2f else 0.8f
MasonryPostItem ( post = post , aspectRatio = aspectRatio )
MasonryPostItem ( post = post , aspectRatio = aspectRatio )
@ -521,6 +851,7 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
Card (
Card (
shape = RoundedCornerShape ( 12. dp ) ,
shape = RoundedCornerShape ( 12. dp ) ,
elevation = CardDefaults . cardElevation ( defaultElevation = 2. dp ) ,
elevation = CardDefaults . cardElevation ( defaultElevation = 2. dp ) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp ) ,
modifier = Modifier
modifier = Modifier
. fillMaxWidth ( )
. fillMaxWidth ( )
. aspectRatio ( aspectRatio )
. aspectRatio ( aspectRatio )
@ -556,28 +887,23 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
Column (
Column (
modifier = Modifier
modifier = Modifier
. align ( Alignment . BottomStart )
. align ( Alignment . BottomStart )
. padding ( 2 .dp ) ,
. padding ( 8 .dp ) ,
verticalArrangement = Arrangement . spacedBy ( 2. dp )
verticalArrangement = Arrangement . spacedBy ( 2. dp )
) {
) {
if ( ! post . feeling . isNullOrBlank ( ) ) {
if ( ! post . feeling . isNullOrBlank ( ) ) {
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . Center
) {
Text (
Text (
text = post . feeling ,
text = post . feeling ,
color = Color . White . copy ( alpha = 0.9f ) ,
color = Color . White . copy ( alpha = 0.9f ) ,
fontSize = 8 .sp ,
fontSize = 9. sp ,
fontWeight = FontWeight . Bold
fontWeight = FontWeight . Bold
)
)
}
}
}
if ( ! post . content . isNullOrBlank ( ) ) {
if ( ! post . content . isNullOrBlank ( ) ) {
Text (
Text (
text = post . content ,
text = post . content ,
color = Color . White ,
color = Color . White ,
fontSize = 10 . sp ,
fontSize = 11 . sp ,
maxLines = 1 ,
maxLines = 2 ,
overflow = TextOverflow . Ellipsis
overflow = TextOverflow . Ellipsis
)
)
}
}
@ -586,55 +912,21 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
Column (
Column (
modifier = Modifier
modifier = Modifier
. fillMaxSize ( )
. fillMaxSize ( )
. background ( BrandPurple . copy ( alpha = 0.8f ) )
. padding ( 10. dp ) ,
. padding ( 10. dp ) ,
verticalArrangement = Arrangement . SpaceBetween
verticalArrangement = Arrangement . SpaceBetween
) {
) {
Row (
modifier = Modifier . fillMaxWidth ( ) ,
horizontalArrangement = Arrangement . SpaceBetween ,
verticalAlignment = Alignment . CenterVertically
) {
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 3. dp )
) {
Icon (
imageVector = when ( post . post_type . lowercase ( ) ) {
" music " -> Icons . Default . MusicNote
else -> Icons . Default . TextSnippet
} ,
contentDescription = null ,
tint = Color . White ,
modifier = Modifier . size ( 10. dp )
)
Text (
Text (
text = post . post_type . uppercase ( ) ,
text = post . post_type . uppercase ( ) ,
color = Color . White . copy ( alpha = 0.9f ) ,
color = Color . White . copy ( alpha = 0.9f ) ,
fontSize = 7 .sp ,
fontSize = 8. sp ,
fontWeight = FontWeight . ExtraBold
fontWeight = FontWeight . ExtraBold
)
)
}
}
Column ( verticalArrangement = Arrangement . spacedBy ( 4. dp ) ) {
Column ( verticalArrangement = Arrangement . spacedBy ( 4. dp ) ) {
if ( ! post . feeling . isNullOrBlank ( ) ) {
if ( ! post . content . isNullOrBlank ( ) ) {
Surface (
shape = RoundedCornerShape ( 6. dp ) ,
color = Color . White . copy ( alpha = 0.2f )
) {
Text (
text = " feeling ${post.feeling} " ,
color = Color . White ,
fontSize = 7. sp ,
modifier = Modifier . padding ( horizontal = 4. dp , vertical = 2. dp ) ,
maxLines = 1 ,
overflow = TextOverflow . Ellipsis
)
}
}
Text (
Text (
text = post . content ?: " " ,
text = post . content ,
color = Color . White ,
color = Color . White ,
fontSize = 11. sp ,
fontSize = 11. sp ,
fontWeight = FontWeight . SemiBold ,
fontWeight = FontWeight . SemiBold ,
@ -643,6 +935,7 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
lineHeight = 14. sp
lineHeight = 14. sp
)
)
}
}
}
Row (
Row (
verticalAlignment = Alignment . CenterVertically ,
verticalAlignment = Alignment . CenterVertically ,