@ -7,6 +7,11 @@ import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
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.background
import androidx.compose.foundation.border
@ -18,17 +23,15 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
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.Close
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FlashO n
import androidx.compose.material.icons.filled.Mood
import androidx.compose.material.icons.filled.KeyboardArrowDow n
import androidx.compose.material.icons.filled.KeyboardArrowUp
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.TextSnippet
import androidx.compose.material.icons.outlined.LocationOn
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
@ -48,18 +51,12 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage
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.FriendProfileResponse
import com.example.dattingapp.homes.profile.LikedUserResponse
import com.example.dattingapp.ui.theme.*
import java.time.LocalDate
import java.time.Period
import java.time.format.DateTimeFormatter
import kotlin.jvm.java
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
class FriendProfile : ComponentActivity ( ) {
override fun onCreate ( savedInstanceState : Bundle ? ) {
@ -126,9 +123,9 @@ fun FriendProfileScreen(
val matchesViewModel : MatchesViewModel = viewModel ( )
// Collect response states
val likesState by likedViewModel . likesUiState . collectAsState ( ) // Users who liked me
val likedState by likedViewModel . likedUiState . collectAsState ( ) // Users I liked
val matchesState by matchesViewModel . state . collectAsState ( ) // Match list from server
val likesState by likedViewModel . likesUiState . collectAsState ( )
val likedState by likedViewModel . likedUiState . collectAsState ( )
val matchesState by matchesViewModel . state . collectAsState ( )
// Fetch lists once
LaunchedEffect ( Unit ) {
@ -154,16 +151,12 @@ fun FriendProfileScreen(
// Track local tap in current screen session
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
// =========================================================================
// STEP 1: Check online match list first
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
// Final match decision
val isMatched = isOnlineMatch || isLocalMatch
// Derived button flags
@ -175,176 +168,174 @@ fun FriendProfileScreen(
calculateAge ( friendProfileData . birth_date )
}
val scrollState = rememberScrollState ( )
Column (
modifier = Modifier
. fillMaxSize ( )
. background ( Color . White )
. verticalScroll ( rememberScrollState ( ) )
. verticalScroll ( scrollState )
. padding ( 16. dp )
) {
// Header Cover & Profile Avatar
Box (
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
)
// ====================================================
// 1. HEADER: Active Now & Action Icons
// ====================================================
Row (
modifier = Modifier
. fillMaxWidth ( )
. padding ( horizontal = 16. dp , vertical = 25. dp ) ,
modifier = Modifier . fillMaxWidth ( ) ,
horizontalArrangement = Arrangement . SpaceBetween ,
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 (
onClick = onBackClick ,
modifier = Modifier . size ( 20. dp ) . clip ( CircleShape )
modifier = Modifier
. size ( 36. dp )
. clip ( CircleShape )
. background ( Color ( 0xFFF7F7F7 ) )
) {
Icon (
imageVector = Icons . AutoMirrored . Filled . ArrowBack ,
contentDescription = " back button "
contentDescription = " Back " ,
tint = textDark ,
modifier = Modifier . size ( 18. dp )
)
}
IconButton (
onClick = onMoreClick ,
modifier = Modifier . size ( 20. dp ) . clip ( CircleShape )
modifier = Modifier
. size ( 36. dp )
. clip ( CircleShape )
. background ( Color ( 0xFFF7F7F7 ) )
) {
Icon (
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 (
model = friendProfileData . profile_image_url ,
contentDescription = " Profile Avatar " ,
model = friendProfileData . profile_image_url ?: " https://picsum.photos/300/300 " ,
contentDescription = " Profile Picture " ,
contentScale = ContentScale . Crop ,
placeholder = painterResource ( id = R . drawable . locationpermissionbg ) ,
error = painterResource ( id = R . drawable . locationpermissionbg ) ,
modifier = Modifier
. padding ( start = 20. dp )
. align ( Alignment . BottomStart )
. size ( 100. dp )
. fillMaxSize ( )
. clip ( CircleShape )
. border ( 4. dp , Color . White , CircleShape ) ,
contentScale = ContentScale . Crop
)
}
Spacer ( modifier = Modifier . height ( 12. dp ) )
// Profile Main Details
Column (
modifier = Modifier
. fillMaxWidth ( )
. padding ( horizontal = 20. dp )
) {
Column ( verticalArrangement = Arrangement . spacedBy ( 4. dp ) ) {
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 8 .dp )
horizontalArrangement = Arrangement . spacedBy ( 6. dp )
) {
val displayName = friendProfileData . full_name ?: " User "
val nameAndAge = if ( age != null ) " $displayName , $age " else displayName
val displayName = friendProfileData . full_name ?: " Alex Rivera "
Text (
text = nameAndAg e,
fontSize = 24 . sp ,
text = displayName ,
fontSize = 20 . sp ,
fontWeight = FontWeight . Bold ,
color = textDark
)
Surface (
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 )
)
if ( age != null ) {
Text (
text = " ${friendProfileData.county ?: 0} % Match " ,
color = Color . White ,
fontSize = 10. sp ,
fontWeight = FontWeight . Bold
text = " $age " ,
fontSize = 20. sp ,
fontWeight = FontWeight . Normal ,
color = textDark
)
}
}
}
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . spacedBy ( 4. dp ) ,
modifier = Modifier . padding ( vertical = 4. dp )
) {
Icon (
imageVector = Icons . Outlined . LocationOn ,
contentDescription = null ,
tint = Color . Gray ,
modifier = Modifier . size ( 14. dp )
)
Text (
text = " ${friendProfileData.city ?: "Unknown"} , ${friendProfileData.country ?: ""} " ,
fontSize = 12. sp ,
color = Color . Gray
imageVector = Icons . Default . Check ,
contentDescription = " Verified " ,
tint = BrandMagenta ,
modifier = Modifier . size ( 16. dp )
)
}
Surface (
modifier = Modifier
. fillMaxWidth ( )
. padding ( vertical = 8. dp ) ,
shape = RoundedCornerShape ( 12. dp ) ,
color = Color ( 0xFFF9F9F9 ) ,
shadowElevation = 1. dp
) {
val city = friendProfileData . city ?: " New York "
Text (
text = friendProfileData . bio ?: " " ,
fontSize = 13. sp ,
color = Color ( 0xFF4A4A4A ) ,
modifier = Modifier . padding ( 12. dp ) ,
maxLines = 2 ,
lineHeight = 18. sp
text = " 📍 $city , NY • 2 miles away " ,
fontSize = 12. sp ,
color = BrandPurple ,
fontWeight = FontWeight . SemiBold
)
}
}
// =========================================================================
// ACTION BUTTON ROW WITH EVALUATED MATCH STATES
// =========================================================================
Spacer ( modifier = Modifier . height ( 16. dp ) )
// ====================================================
// 3. ACTION BUTTON ROW (Message, Like, Super Like, Dislike)
// ====================================================
Row (
modifier = Modifier
. fillMaxWidth ( )
. padding ( vertical = 8 .dp ) ,
horizontalArrangement = Arrangement . spacedBy ( 10 .dp ) ,
. padding ( vertical = 4 .dp ) ,
horizontalArrangement = Arrangement . spacedBy ( 8 .dp ) ,
verticalAlignment = Alignment . CenterVertically
) {
// 💬 Message Button — Enabled ONLY when matched
// 💬 Message Button
Card (
onClick = onMessageClick ,
enabled = isMessageClickable ,
modifier = Modifier
. weight ( 1f )
. height ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors (
containerColor = if ( isMessageClickable ) Color . White else Color ( 0xFFF0F0F0 ) ,
disabledContainerColor = Color ( 0xFFF0F0F0 )
) ,
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 (
modifier = Modifier . fillMaxSize ( ) ,
@ -355,12 +346,12 @@ fun FriendProfileScreen(
imageVector = Icons . Default . ChatBubble ,
contentDescription = " Message " ,
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 = " Message " ,
fontSize = 16 . sp ,
fontSize = 14 . sp ,
fontWeight = FontWeight . Bold ,
color = if ( isMessageClickable ) textDark else Color ( 0xFFBDBDBD )
)
@ -369,7 +360,6 @@ fun FriendProfileScreen(
// ❤️ Like & ⭐ Super Like Buttons — Hidden when matched
if ( showLikeAndSuperLike ) {
// ❤️ Like Button
Card (
onClick = {
onLikeClick ( )
@ -379,14 +369,15 @@ fun FriendProfileScreen(
} ,
enabled = ! likeDisabled ,
modifier = Modifier . size ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors (
containerColor = if ( heLikedMe ) Color ( 0xFFE53935 ) else Color . White ,
disabledContainerColor = if ( heLikedMe ) Color ( 0xFFE53935 ) else Color ( 0xFFF0F0F0 )
) ,
elevation = CardDefaults . cardElevation (
defaultElevation = if ( likeDisabled ) 0. dp else 2. dp
)
) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Icon (
@ -402,7 +393,6 @@ fun FriendProfileScreen(
}
}
// ⭐ Super Like (Star) Button
Card (
onClick = {
onStarClick ( )
@ -412,14 +402,15 @@ fun FriendProfileScreen(
} ,
enabled = ! likeDisabled ,
modifier = Modifier . size ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
colors = CardDefaults . cardColors (
containerColor = Color . White ,
disabledContainerColor = Color ( 0xFFF0F0F0 )
) ,
elevation = CardDefaults . cardElevation (
defaultElevation = if ( likeDisabled ) 0. dp else 2. dp
)
) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp )
) {
Box ( modifier = Modifier . fillMaxSize ( ) , contentAlignment = Alignment . Center ) {
Icon (
@ -432,21 +423,21 @@ fun FriendProfileScreen(
}
}
// ❌ Cancel / Dislike Button — Resets everything back to initial state
// ❌ Dislike / Cancel Button
Card (
onClick = {
onCancelClick ( )
handleLikeAndDislikeAction ( context , " pass " , friendProfileData , swipeViewModel )
localLiked = false
likedViewModel . likedResponse ( context , " Likes " )
likedViewModel . likedResponse ( context , " Liked " )
matchesViewModel . loadMatches ( context )
} ,
modifier = Modifier . size ( 48. dp ) ,
shape = RoundedCornerShape ( 10 . dp ) ,
shape = RoundedCornerShape ( 12 . dp ) ,
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 ) {
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 ) )
// 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 = " Posts " ,
fontSize = 18. sp ,
fontSize = 16 . sp ,
fontWeight = FontWeight . Bold ,
color = textDark ,
modifier = Modifier . padding ( bottom = 8. dp )
)
Spacer ( modifier = Modifier . height ( 16. dp ) )
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 (
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 ->
val aspectRatio = if ( idx % 2 == 0 ) 0.8f else 1.2f
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 ->
val aspectRatio = if ( idx % 2 == 0 ) 1.2f else 0.8f
MasonryPostItem ( post = post , aspectRatio = aspectRatio )
@ -521,6 +851,7 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
Card (
shape = RoundedCornerShape ( 12. dp ) ,
elevation = CardDefaults . cardElevation ( defaultElevation = 2. dp ) ,
border = CardDefaults . outlinedCardBorder ( ) . copy ( width = 0.5 . dp ) ,
modifier = Modifier
. fillMaxWidth ( )
. aspectRatio ( aspectRatio )
@ -556,28 +887,23 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
Column (
modifier = Modifier
. align ( Alignment . BottomStart )
. padding ( 2 .dp ) ,
. padding ( 8 .dp ) ,
verticalArrangement = Arrangement . spacedBy ( 2. dp )
) {
if ( ! post . feeling . isNullOrBlank ( ) ) {
Row (
verticalAlignment = Alignment . CenterVertically ,
horizontalArrangement = Arrangement . Center
) {
Text (
text = post . feeling ,
color = Color . White . copy ( alpha = 0.9f ) ,
fontSize = 8 .sp ,
fontSize = 9. sp ,
fontWeight = FontWeight . Bold
)
}
}
if ( ! post . content . isNullOrBlank ( ) ) {
Text (
text = post . content ,
color = Color . White ,
fontSize = 10 . sp ,
maxLines = 1 ,
fontSize = 11 . sp ,
maxLines = 2 ,
overflow = TextOverflow . Ellipsis
)
}
@ -586,55 +912,21 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
Column (
modifier = Modifier
. fillMaxSize ( )
. background ( BrandPurple . copy ( alpha = 0.8f ) )
. padding ( 10. dp ) ,
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 = post . post_type . uppercase ( ) ,
color = Color . White . copy ( alpha = 0.9f ) ,
fontSize = 7 .sp ,
fontSize = 8. sp ,
fontWeight = FontWeight . ExtraBold
)
}
}
Column ( verticalArrangement = Arrangement . spacedBy ( 4. dp ) ) {
if ( ! post . feeling . 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
)
}
}
if ( ! post . content . isNullOrBlank ( ) ) {
Text (
text = post . content ?: " " ,
text = post . content ,
color = Color . White ,
fontSize = 11. sp ,
fontWeight = FontWeight . SemiBold ,
@ -643,6 +935,7 @@ fun MasonryPostItem(post: FriendPost, aspectRatio: Float) {
lineHeight = 14. sp
)
}
}
Row (
verticalAlignment = Alignment . CenterVertically ,