diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/HomeScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/HomeScreen.kt index bc5ec3c..0d2779e 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/HomeScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/HomeScreen.kt @@ -37,3 +37,4 @@ fun HomeScreen( } } } + diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileScreen.kt index 70d85a0..5d2283f 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileScreen.kt @@ -1,70 +1,332 @@ package com.pwhs.quickmem.presentation.app.profile +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material.icons.filled.Share +import androidx.compose.material3.* +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.hilt.navigation.compose.hiltViewModel +import androidx.compose.ui.draw.clip +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 com.pwhs.quickmem.R import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph -import com.ramcosta.composedestinations.generated.destinations.WelcomeScreenDestination -import com.ramcosta.composedestinations.navigation.DestinationsNavigator @Composable @Destination fun ProfileScreen( modifier: Modifier = Modifier, - viewModel: ProfileViewModel = hiltViewModel(), - navigator: DestinationsNavigator + navigateToSettings: () -> Unit = {}, + navigateToShare: () -> Unit = {} ) { - val uiState by viewModel.uiState.collectAsState() - LaunchedEffect(key1 = true) { - viewModel.uiEvent.collect { event -> - when (event) { - is ProfileUiEvent.LoadProfile -> TODO() - ProfileUiEvent.Logout -> { - navigator.navigateUp() - navigator.navigate(WelcomeScreenDestination) { - popUpTo(WelcomeScreenDestination) { inclusive = true } + var tabIndex by remember { mutableIntStateOf(0) } + val tabTitles = listOf("Profile", "Statistics") + + Scaffold( + modifier = modifier, + bottomBar = { /* Add a bottom bar if needed */ } + ) { innerPadding -> + Box( + modifier = Modifier + .background(Color.Transparent) + .padding(innerPadding) + ) { + Image( + painter = painterResource(id = R.drawable.background_topbar), + contentDescription = "Background Image", + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxWidth().height(58.dp) + ) + + + LazyColumn { + item { + ProfileTopAppBar( + onSettingsClick = navigateToSettings, + onShareClick = navigateToShare + ) + } + item { + ProfileTabRow(tabIndex = tabIndex, tabTitles = tabTitles, onTabSelected = { tabIndex = it }) + } + item { + ProfileTabContent(tabIndex = tabIndex, onLogout = { /* Handle logout here */ }) + } + } + } + } +} + + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ProfileTopAppBar( + onSettingsClick: () -> Unit, + onShareClick: () -> Unit +) { + CenterAlignedTopAppBar( + title = {}, + navigationIcon = { + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(end = 30.dp) + ) { + Box( + modifier = Modifier + .size(40.dp) + .background(Color.White, shape = CircleShape) + .border(1.dp, Color.Gray, shape = CircleShape) + ) { + IconButton(onClick = onSettingsClick, modifier = Modifier.fillMaxSize()) { + Icon( + imageVector = Icons.Default.Settings, + contentDescription = "Settings", + tint = Color.Gray, + ) + } + } + + Spacer(modifier = Modifier.width(10.dp)) + + Box( + modifier = Modifier + .size(40.dp) + .background(Color.White, shape = CircleShape) + .border(1.dp, Color.Gray, shape = CircleShape) + ) { + IconButton(onClick = onShareClick, modifier = Modifier.fillMaxSize()) { + Icon( + imageVector = Icons.Default.Share, + contentDescription = "Share Profile", + tint = Color.Gray, + ) } } } + }, + actions = {}, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + containerColor = Color.Transparent + ) + ) +} +@Composable +fun ProfileTabRow(tabIndex: Int, tabTitles: List, onTabSelected: (Int) -> Unit) { + TabRow( + selectedTabIndex = tabIndex, + indicator = { tabPositions -> + TabRowDefaults.SecondaryIndicator( + Modifier.tabIndicatorOffset(tabPositions[tabIndex]), + color = MaterialTheme.colorScheme.primary, + ) + }, + contentColor = MaterialTheme.colorScheme.onSurface, + ) { + tabTitles.forEachIndexed { index, title -> + Tab( + text = { + Text( + title, + style = MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Bold, + color = if (tabIndex == index) Color.Black else Color.Gray + ) + ) + }, + selected = tabIndex == index, + onClick = { onTabSelected(index) } + ) } } - Profile( - onLogout = { viewModel.onEvent(ProfileUiAction.Logout) } +} + +@Composable +fun ProfileTabContent(tabIndex: Int, onLogout: () -> Unit) { + when (tabIndex) { + 0 -> ProfileOverviewScreen() + 1 -> StatisticsScreen() + } +} + +@Composable +fun ProfileOverviewScreen() { + ProfileContent() +} + +@Composable +fun StatisticsScreen() { + Text( + text = "Statistics Content", + modifier = Modifier.padding(16.dp), + style = MaterialTheme.typography.bodyLarge ) } @Composable -fun Profile( - modifier: Modifier = Modifier, - onLogout: () -> Unit = {} -) { - Scaffold { innerPadding -> +fun ProfileContent() { + var name by remember { mutableStateOf("Huấn") } + var email by remember { mutableStateOf("huanhvph35061@fpt.edu.vn") } + var status by remember { mutableStateOf("Student (high / secondary school)") } + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .border(1.dp, Color.Gray, shape = MaterialTheme.shapes.small) + .clip(MaterialTheme.shapes.small) + .padding(16.dp) + ) { Column( - modifier = modifier - .fillMaxSize() - .padding(innerPadding), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + verticalArrangement = Arrangement.spacedBy(16.dp) ) { - Text("Profile Screen") - Button( - onClick = onLogout + + OutlinedTextField( + value = name, + onValueChange = { name = it }, + label = { Text("Name") }, + modifier = Modifier.fillMaxWidth() + ) + + + OutlinedTextField( + value = email, + onValueChange = { email = it }, + label = { Text("Email") }, + modifier = Modifier.fillMaxWidth() + ) + + + Text( + text = "Please confirm your email address via the email we sent you", + color = Color.Red, + style = MaterialTheme.typography.bodySmall + ) + + Box( + modifier = Modifier + .align(Alignment.Start) + .height(38.dp) + .border(1.dp, Color.Gray, shape = RoundedCornerShape(25.dp)) + .clip(RoundedCornerShape(25.dp)) + .clickable { /* Add resend email functionality */ } + .padding(8.dp) + .background(Color.White) + ) { + Text( + text = "Resend email", + color = Color.Black, + modifier = Modifier.padding(2.dp) + ) + } + + + OutlinedTextField( + value = status, + onValueChange = { /* Implement logic to change status */ }, + label = { Text("Status") }, + readOnly = true, + modifier = Modifier.fillMaxWidth() + ) + + Box( + modifier = Modifier + .align(Alignment.Start) + .height(38.dp) + .border(1.dp, Color.Gray, shape = RoundedCornerShape(25.dp)) + .clip(RoundedCornerShape(25.dp)) + .clickable { /* Add resend email functionality */ } + .padding(8.dp) + .background(Color.White) ) { - Text("Logout") + Text( + text = "Edit education information", + color = Color.Black, + modifier = Modifier.padding(2.dp) + ) } + + Box( + modifier = Modifier + .fillMaxWidth() + .border(1.dp, Color.Gray, shape = MaterialTheme.shapes.small) + .clip(MaterialTheme.shapes.small) + .padding(16.dp) + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + + Image( + painter = painterResource(id = R.drawable.share_togethe), + contentDescription = null, + modifier = Modifier + .width(250.dp) + .height(130.dp) + .clip(RoundedCornerShape(20.dp)) + .align(Alignment.CenterHorizontally) + ) + + Text("Study together", style = MaterialTheme.typography.titleMedium) + Text("Friends referred: 0", style = MaterialTheme.typography.bodySmall) + + Box( + modifier = Modifier + .fillMaxWidth() + .height(38.dp) + .border(1.dp, Color.Gray, shape = RoundedCornerShape(25.dp)) + .clip(RoundedCornerShape(25.dp)) + .clickable { /* Add share functionality */ } + .background(Color.White) + ) { + + Text( + text = "Share", + color = Color.Black, + modifier = Modifier + .padding(12.dp) + .align(Alignment.Center) + ) + } + } + } + } } -} \ No newline at end of file +} + + + +@Preview(showBackground = true) +@Composable +fun PreviewProfileScreen() { + ProfileScreen() +} diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileUiState.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileUiState.kt index 5d98ef3..bc17178 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileUiState.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/profile/ProfileUiState.kt @@ -2,5 +2,6 @@ package com.pwhs.quickmem.presentation.app.profile data class ProfileUiState( val isLoading: Boolean = false, - val error: String = "", + val error: String? = null, + ) \ No newline at end of file diff --git a/app/src/main/res/drawable/background_topbar.jpg b/app/src/main/res/drawable/background_topbar.jpg new file mode 100644 index 0000000..a1ae0f3 Binary files /dev/null and b/app/src/main/res/drawable/background_topbar.jpg differ diff --git a/app/src/main/res/drawable/ic_setting.png b/app/src/main/res/drawable/ic_setting.png new file mode 100644 index 0000000..7f21dcb Binary files /dev/null and b/app/src/main/res/drawable/ic_setting.png differ diff --git a/app/src/main/res/drawable/ic_share.png b/app/src/main/res/drawable/ic_share.png new file mode 100644 index 0000000..7692eea Binary files /dev/null and b/app/src/main/res/drawable/ic_share.png differ diff --git a/app/src/main/res/drawable/share_togethe.jpg b/app/src/main/res/drawable/share_togethe.jpg new file mode 100644 index 0000000..31f363c Binary files /dev/null and b/app/src/main/res/drawable/share_togethe.jpg differ