This is a dating app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

931 lines
21 KiB

package com.example.dattingapp
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
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.Check
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.GridView
import androidx.compose.material.icons.outlined.PersonPin
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.dattingapp.ui.theme.BrandMagenta
import com.example.dattingapp.ui.theme.BrandPurple
import com.example.dattingapp.ui.theme.DattingAPPTheme
import com.example.dattingapp.ui.theme.textDark
import com.example.dattingapp.ui.theme.TextMuted
// ============================================================
// MY PROFILE ACTIVITY
// ============================================================
class MyProfile : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
DattingAPPTheme {
MyProfileScreen(
onEditClick = {
Toast.makeText(
this,
"Edit Profile Clicked",
Toast.LENGTH_SHORT
).show()
// TODO:
// startActivity(
// Intent(
// this,
// EditProfileActivity::class.java
// )
// )
},
onUpgradeClick = {
Toast.makeText(
this,
"Upgrade to Premium Clicked",
Toast.LENGTH_SHORT
).show()
},
onSettingsClick = {
Toast.makeText(
this,
"Settings Clicked",
Toast.LENGTH_SHORT
).show()
// TODO:
// startActivity(
// Intent(
// this,
// SettingsActivity::class.java
// )
// )
}
)
}
}
}
}
// ============================================================
// MY PROFILE SCREEN
// ============================================================
@Composable
fun MyProfileScreen(
onEditClick: () -> Unit = {},
onUpgradeClick: () -> Unit = {},
onSettingsClick: () -> Unit = {}
) {
var selectedTab by remember {
mutableIntStateOf(0)
}
// ========================================================
// FULL SCREEN SCROLL
// ========================================================
val scrollState =
rememberScrollState()
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.verticalScroll(scrollState)
) {
// ====================================================
// HEADER
// ====================================================
Box(
modifier = Modifier
.fillMaxWidth()
.height(260.dp)
) {
// =================================================
// COVER IMAGE
// =================================================
Image(
painter =
painterResource(
id =
R.drawable.locationpermissionbg
),
contentDescription =
"Cover Banner",
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
contentScale =
ContentScale.Crop
)
// =================================================
// SETTINGS BUTTON
// =================================================
IconButton(
onClick =
onSettingsClick,
modifier = Modifier
.align(
Alignment.TopEnd
)
.padding(
top = 16.dp,
end = 16.dp
)
.size(36.dp)
.clip(
CircleShape
)
.background(
Color.Black.copy(
alpha = 0.3f
)
)
) {
Icon(
imageVector =
Icons.Outlined.Settings,
contentDescription =
"Settings",
tint =
Color.White,
modifier =
Modifier.size(20.dp)
)
}
// =================================================
// PROFILE IMAGE
// =================================================
Box(
modifier = Modifier
.align(
Alignment.BottomStart
)
.padding(
start = 24.dp
)
.size(110.dp)
) {
Image(
painter =
painterResource(
id =
R.drawable.locationpermissionbg
),
contentDescription =
"Profile Picture",
contentScale =
ContentScale.Crop,
modifier = Modifier
.fillMaxSize()
.clip(
CircleShape
)
.border(
width = 4.dp,
color = Color.White,
shape = CircleShape
)
)
// =================================================
// VERIFIED BADGE
// =================================================
Box(
modifier = Modifier
.align(
Alignment.BottomEnd
)
.size(28.dp)
.clip(
CircleShape
)
.background(
BrandMagenta
)
.border(
width = 2.dp,
color = Color.White,
shape = CircleShape
),
contentAlignment =
Alignment.Center
) {
Icon(
imageVector =
Icons.Default.Check,
contentDescription =
"Verified",
tint =
Color.White,
modifier =
Modifier.size(16.dp)
)
}
}
}
// ====================================================
// USER INFORMATION
// ====================================================
Column(
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = 24.dp,
vertical = 8.dp
)
) {
// =================================================
// NAME + EDIT
// =================================================
Row(
verticalAlignment =
Alignment.CenterVertically,
horizontalArrangement =
Arrangement.spacedBy(8.dp)
) {
Text(
text =
"Alex, 28",
fontSize =
22.sp,
fontWeight =
FontWeight.Bold,
color =
BrandMagenta
)
// EDIT BUTTON
OutlinedButton(
onClick =
onEditClick,
modifier =
Modifier.height(30.dp),
contentPadding =
PaddingValues(
horizontal = 10.dp,
vertical = 0.dp
),
border =
ButtonDefaults
.outlinedButtonBorder
.copy(
width = 1.dp
)
) {
Icon(
imageVector =
Icons.Outlined.Edit,
contentDescription =
null,
tint =
BrandMagenta,
modifier =
Modifier.size(14.dp)
)
Spacer(
modifier =
Modifier.width(4.dp)
)
Text(
text =
"Edit",
fontSize =
12.sp,
color =
BrandMagenta,
fontWeight =
FontWeight.Bold
)
}
}
Spacer(
modifier =
Modifier.height(4.dp)
)
// =================================================
// BIO
// =================================================
Text(
text =
"Adventure seeker, dog lover, and amateur chef. Let's find a vibe!",
fontSize =
13.sp,
color =
TextMuted,
lineHeight =
18.sp
)
}
Spacer(
modifier =
Modifier.height(12.dp)
)
// ====================================================
// PREMIUM BANNER
// ====================================================
Box(
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = 16.dp
)
.clip(
RoundedCornerShape(16.dp)
)
.background(
brush =
Brush.horizontalGradient(
colors =
listOf(
BrandMagenta,
BrandPurple
)
)
)
.padding(16.dp)
) {
Row(
modifier =
Modifier.fillMaxWidth(),
horizontalArrangement =
Arrangement.SpaceBetween,
verticalAlignment =
Alignment.CenterVertically
) {
Column {
Text(
text =
"VibeCheck Premium",
color =
Color.White,
fontSize =
16.sp,
fontWeight =
FontWeight.Bold
)
Spacer(
modifier =
Modifier.height(2.dp)
)
Text(
text =
"Unlock unlimited likes & more",
color =
Color.White.copy(
alpha = 0.8f
),
fontSize =
12.sp
)
}
// UPGRADE BUTTON
Button(
onClick =
onUpgradeClick,
colors =
ButtonDefaults.buttonColors(
containerColor =
Color.White
),
shape =
RoundedCornerShape(20.dp),
contentPadding =
PaddingValues(
horizontal = 14.dp,
vertical = 4.dp
)
) {
Text(
text =
"Upgrade",
color =
BrandMagenta,
fontSize =
12.sp,
fontWeight =
FontWeight.Bold
)
}
}
}
Spacer(
modifier =
Modifier.height(16.dp)
)
// ====================================================
// STATISTICS
// ====================================================
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = 16.dp
),
horizontalArrangement =
Arrangement.spacedBy(8.dp)
) {
StatCard(
number =
"24",
label =
"Likes",
modifier =
Modifier.weight(1f)
)
StatCard(
number =
"12",
label =
"Liked",
modifier =
Modifier.weight(1f)
)
StatCard(
number =
"Top",
label =
"Match",
numberColor =
BrandMagenta,
modifier =
Modifier.weight(1f)
)
StatCard(
number =
"8",
label =
"Matches",
modifier =
Modifier.weight(1f)
)
}
Spacer(
modifier =
Modifier.height(16.dp)
)
// ====================================================
// TABS
// ====================================================
TabRow(
selectedTabIndex =
selectedTab,
containerColor =
Color.White,
contentColor =
BrandMagenta,
divider = {
HorizontalDivider(
color =
Color(0xFFEEEEEE)
)
}
) {
// =================================================
// GRID TAB
// =================================================
Tab(
selected =
selectedTab == 0,
onClick = {
selectedTab = 0
},
icon = {
Icon(
imageVector =
Icons.Outlined.GridView,
contentDescription =
"Grid View"
)
}
)
// =================================================
// TAGGED TAB
// =================================================
Tab(
selected =
selectedTab == 1,
onClick = {
selectedTab = 1
},
icon = {
Icon(
imageVector =
Icons.Outlined.PersonPin,
contentDescription =
"Tagged View"
)
}
)
}
// ====================================================
// MEDIA GRID
// ====================================================
ProfileMediaGrid()
Spacer(
modifier =
Modifier.height(30.dp)
)
}
}
// ============================================================
// PROFILE MEDIA GRID
// ============================================================
@Composable
private fun ProfileMediaGrid() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(2.dp)
) {
// 6 rows × 3 columns = 18 images
repeat(6) { rowIndex ->
Row(
modifier =
Modifier.fillMaxWidth()
) {
repeat(3) { columnIndex ->
val imageIndex =
rowIndex * 3 +
columnIndex
Image(
painter =
painterResource(
id =
R.drawable.locationpermissionbg
),
contentDescription =
"Profile Image $imageIndex",
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
.padding(1.dp),
contentScale =
ContentScale.Crop
)
}
}
}
}
}
// ============================================================
// STAT CARD
// ============================================================
@Composable
private fun StatCard(
number: String,
label: String,
modifier: Modifier = Modifier,
numberColor: Color = textDark
) {
Card(
modifier =
modifier,
shape =
RoundedCornerShape(12.dp),
colors =
CardDefaults.cardColors(
containerColor =
Color(0xFFFAFAFA)
),
border =
CardDefaults
.outlinedCardBorder()
.copy(
width = 0.5.dp
)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(
vertical = 12.dp
),
horizontalAlignment =
Alignment.CenterHorizontally
) {
Text(
text =
number,
fontSize =
16.sp,
fontWeight =
FontWeight.Bold,
color =
numberColor
)
Spacer(
modifier =
Modifier.height(2.dp)
)
Text(
text =
label,
fontSize =
11.sp,
color =
TextMuted
)
}
}
}
// ============================================================
// PREVIEW
// ============================================================
@Preview(
showBackground = true,
showSystemUi = true,
name = "My Profile"
)
@Composable
fun MyProfileScreenPreview() {
DattingAPPTheme {
MyProfileScreen()
}
}