From 3bc6c89307d4948eaeb67d5c691de97be9bba9af Mon Sep 17 00:00:00 2001 From: soyuo Date: Wed, 27 May 2026 17:28:08 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat(profile):=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EA=B4=80=EB=A0=A8=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=8F=20=ED=99=94=EB=A9=B4=20=EC=9D=B4=EB=8F=99=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/it_da/navigation/AppNavigation.kt | 76 ++++++++++++++++++- .../com/example/it_da/navigation/AppRoute.kt | 6 ++ .../example/it_da/ui/screen/home/HomeRoute.kt | 3 +- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/example/it_da/navigation/AppNavigation.kt b/app/src/main/java/com/example/it_da/navigation/AppNavigation.kt index bbb9777..f01b30a 100644 --- a/app/src/main/java/com/example/it_da/navigation/AppNavigation.kt +++ b/app/src/main/java/com/example/it_da/navigation/AppNavigation.kt @@ -6,6 +6,12 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import com.example.it_da.ui.screen.home.HomeRoute import com.example.it_da.ui.screen.login.LoginRoute +import com.example.it_da.ui.screen.profile.NotificationSettingsRoute +import com.example.it_da.ui.screen.profile.PersonalInfoRoute +import com.example.it_da.ui.screen.profile.ProfileRoute +import com.example.it_da.ui.screen.profile.ProjectStatusRoute +import com.example.it_da.ui.screen.profile.SelfIntroductionRoute +import com.example.it_da.ui.screen.profile.VersionInfoRoute import com.example.it_da.ui.screen.signup.route.SignUpAccountRoute import com.example.it_da.ui.screen.signup.route.SignUpAdditionalInfoRoute @@ -49,7 +55,75 @@ fun AppNavigation() { } composable(AppRoute.Home.path) { - HomeRoute() + HomeRoute( + onProfileTabClick = { + navController.navigate(AppRoute.Profile.path) + } + ) + } + + composable(AppRoute.Profile.path) { + ProfileRoute( + onHomeTabClick = { + navController.navigate(AppRoute.Home.path) + }, + onNotificationSettingsClick = { + navController.navigate(AppRoute.NotificationSettings.path) + }, + onProjectStatusClick = { + navController.navigate(AppRoute.ProjectStatus.path) + }, + onSelfIntroductionClick = { + navController.navigate(AppRoute.SelfIntroduction.path) + }, + onPersonalInfoClick = { + navController.navigate(AppRoute.PersonalInfo.path) + } + ) + } + + composable(AppRoute.PersonalInfo.path) { + PersonalInfoRoute( + onBackClick = { navController.popBackStack() } + ) + } + + composable(AppRoute.SelfIntroduction.path) { + SelfIntroductionRoute( + onBackClick = { navController.popBackStack() } + ) + } + + composable(AppRoute.ProjectStatus.path) { + ProjectStatusRoute( + onBackClick = { + navController.popBackStack() + } + ) + } + + composable(AppRoute.NotificationSettings.path) { + NotificationSettingsRoute( + onBackClick = { + navController.popBackStack() + }, + onVersionInfoClick = { + navController.navigate(AppRoute.VersionInfo.path) + }, + onSignOutClick = { + navController.navigate(AppRoute.Login.path) { + popUpTo(navController.graph.id) { inclusive = true } + } + } + ) + } + + composable(AppRoute.VersionInfo.path) { + VersionInfoRoute( + onBackClick = { + navController.popBackStack() + } + ) } } } diff --git a/app/src/main/java/com/example/it_da/navigation/AppRoute.kt b/app/src/main/java/com/example/it_da/navigation/AppRoute.kt index cd2d5c4..10838ae 100644 --- a/app/src/main/java/com/example/it_da/navigation/AppRoute.kt +++ b/app/src/main/java/com/example/it_da/navigation/AppRoute.kt @@ -6,4 +6,10 @@ sealed class AppRoute(val path: String) { data object SignUpAccount : AppRoute("sign_up_account") data object SignUpAdditionalInfo : AppRoute("sign_up_additional_info") data object Home : AppRoute("home") + data object Profile : AppRoute("profile") + data object PersonalInfo : AppRoute("personal_info") + data object SelfIntroduction : AppRoute("self_introduction") + data object ProjectStatus : AppRoute("project_status") + data object NotificationSettings : AppRoute("notification_settings") + data object VersionInfo : AppRoute("version_info") } diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/HomeRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/home/HomeRoute.kt index e7e704f..9bc1092 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/HomeRoute.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/HomeRoute.kt @@ -10,6 +10,7 @@ import com.example.it_da.ui.screen.home.viewmodel.HomeViewModelFactory // Connects HomeViewModel state to the home screen and leaves future navigation targets as callbacks. @Composable fun HomeRoute( + onProfileTabClick: () -> Unit = {}, viewModel: HomeViewModel = viewModel(factory = HomeViewModelFactory()) ) { val uiState by viewModel.uiState.collectAsState() @@ -27,6 +28,6 @@ fun HomeRoute( onExploreTabClick = {}, onCreateProjectClick = {}, onNotificationTabClick = {}, - onProfileTabClick = {} + onProfileTabClick = onProfileTabClick ) } From 495dc35e99a7fabb8ed9b32e039edc70eceacc6f Mon Sep 17 00:00:00 2001 From: soyuo Date: Wed, 27 May 2026 17:28:18 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat(profile):=20=EB=82=B4=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84,=20=EC=84=A4=EC=A0=95,=20=ED=98=84=ED=99=A9,?= =?UTF-8?q?=20=EC=9E=90=EA=B8=B0=EC=86=8C=EA=B0=9C,=20=EA=B0=9C=EC=9D=B8?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=9E=85=EB=A0=A5=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/profile/MyProfileScreen.kt | 318 ++++++++++++++++++ .../profile/NotificationSettingsRoute.kt | 16 + .../profile/NotificationSettingsScreen.kt | 313 +++++++++++++++++ .../ui/screen/profile/PersonalInfoRoute.kt | 11 + .../ui/screen/profile/PersonalInfoScreen.kt | 166 +++++++++ .../it_da/ui/screen/profile/ProfileRoute.kt | 25 ++ .../it_da/ui/screen/profile/ProfileScreen.kt | 296 ++++++++++++++++ .../ui/screen/profile/ProjectStatusRoute.kt | 11 + .../ui/screen/profile/ProjectStatusScreen.kt | 228 +++++++++++++ .../screen/profile/SelfIntroductionRoute.kt | 11 + .../screen/profile/SelfIntroductionScreen.kt | 221 ++++++++++++ .../ui/screen/profile/VersionInfoRoute.kt | 11 + .../ui/screen/profile/VersionInfoScreen.kt | 138 ++++++++ 13 files changed, 1765 insertions(+) create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsRoute.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoRoute.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/ProfileRoute.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusRoute.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionRoute.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoRoute.kt create mode 100644 app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt new file mode 100644 index 0000000..5d26dec --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt @@ -0,0 +1,318 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +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.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +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.dp +import androidx.compose.ui.unit.sp +import com.example.it_da.ui.component.ItdaOutlinedBadge +import com.example.it_da.ui.screen.home.component.HomeBottomNavigationBar +import com.example.it_da.ui.screen.signup.component.SignUpTopBar +import com.example.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +@Composable +fun MyProfileScreen( + onHomeTabClick: () -> Unit, + onExploreTabClick: () -> Unit, + onCreateProjectClick: () -> Unit, + onNotificationTabClick: () -> Unit, + onProfileTabClick: () -> Unit, + onNotificationSettingsClick: () -> Unit, + onProjectStatusClick: () -> Unit, + onSelfIntroductionClick: () -> Unit, + onPersonalInfoClick: () -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + ) { + Column(modifier = Modifier.fillMaxSize()) { + SignUpTopBar(title = "Project") + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .padding(top = 22.dp, bottom = 84.dp) + ) { + MyProfileHeader() + Spacer(modifier = Modifier.height(14.dp)) + + ActionButton( + text = "개인 정보 입력", + onClick = onPersonalInfoClick + ) + + Spacer(modifier = Modifier.height(22.dp)) + SectionTitle(text = "기술 스택") + Spacer(modifier = Modifier.height(14.dp)) + Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) { + ItdaOutlinedBadge(text = "Back-end") + ItdaOutlinedBadge(text = "Java") + ItdaOutlinedBadge(text = "JavaScript") + ItdaOutlinedBadge(text = "Design") + } + + Spacer(modifier = Modifier.height(24.dp)) + SectionTitle(text = "경력") + Spacer(modifier = Modifier.height(10.dp)) + EmptyBox(height = 86.dp) + + Spacer(modifier = Modifier.height(20.dp)) + SectionTitle(text = "자기 소개") + Spacer(modifier = Modifier.height(10.dp)) + EmptyBox( + height = 90.dp, + text = "자기소개 작성하기", + onClick = onSelfIntroductionClick + ) + + Spacer(modifier = Modifier.height(20.dp)) + SectionTitle(text = "활동 요약") + Spacer(modifier = Modifier.height(12.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + SummaryCard(value = "2", label = "참여 프로젝트", modifier = Modifier.weight(1f)) + SummaryCard(value = "3", label = "지원 내역", modifier = Modifier.weight(1f)) + SummaryCard(value = "1", label = "받은 제안", modifier = Modifier.weight(1f)) + } + + Spacer(modifier = Modifier.height(12.dp)) + Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { + ActionButton( + text = "프로젝트 전체 보기", + modifier = Modifier.weight(1.35f), + onClick = onProjectStatusClick + ) + ActionButton( + text = "설정", + modifier = Modifier.weight(1f), + onClick = onNotificationSettingsClick + ) + } + } + } + + HomeBottomNavigationBar( + onHomeClick = onHomeTabClick, + onExploreClick = onExploreTabClick, + onCreateProjectClick = onCreateProjectClick, + onNotificationClick = onNotificationTabClick, + onProfileClick = onProfileTabClick, + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + ) + } +} + +@Composable +private fun MyProfileHeader() { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Surface( + modifier = Modifier.size(92.dp), + shape = CircleShape, + color = Color(0xFFE3E3E3) + ) { + Box(contentAlignment = Alignment.Center) { + Surface( + modifier = Modifier.size(38.dp), + shape = CircleShape, + color = Color(0xFF8F8F8F) + ) {} + } + } + + Spacer(modifier = Modifier.size(20.dp)) + + Column { + Text( + text = "메타몽", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 35.sp, + lineHeight = 40.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Text( + text = "SW개발과 · 1학년", + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 23.sp, + lineHeight = 26.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Text( + text = "가입일 2025년 1월", + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 23.sp, + lineHeight = 26.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + } +} + +@Composable +private fun SectionTitle(text: String) { + Text( + text = text, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 27.sp, + lineHeight = 31.sp, + color = MaterialTheme.colorScheme.onBackground + ) +} + +@Composable +private fun EmptyBox( + height: Dp, + text: String? = null, + onClick: (() -> Unit)? = null +) { + Surface( + modifier = Modifier + .fillMaxWidth() + .height(height) + .let { base -> if (onClick != null) base.clickable(onClick = onClick) else base }, + shape = RoundedCornerShape(12.dp), + color = Color.Transparent, + border = BorderStroke(1.2.dp, ItdaGuideGray) + ) { + if (text != null) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = text, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + color = ItdaSecondaryTextColor + ) + } + } + } +} + +@Composable +private fun SummaryCard( + value: String, + label: String, + modifier: Modifier = Modifier +) { + Surface( + modifier = modifier.height(72.dp), + shape = RoundedCornerShape(12.dp), + color = Color.Transparent, + border = BorderStroke(1.2.dp, ItdaGuideGray) + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = value, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 17.sp, + lineHeight = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Spacer(modifier = Modifier.height(3.dp)) + Text( + text = label, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 11.sp, + lineHeight = 13.sp, + color = ItdaSecondaryTextColor + ) + } + } +} + +@Composable +private fun ActionButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit = {} +) { + Surface( + modifier = modifier + .height(50.dp) + .clickable(onClick = onClick), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.2.dp, ItdaGuideGray) + ) { + Box(contentAlignment = Alignment.Center) { + Text( + text = text, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 16.sp, + color = ItdaSecondaryTextColor + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun MyProfileScreenPreview() { + ITDATheme { + MyProfileScreen( + onHomeTabClick = {}, + onExploreTabClick = {}, + onCreateProjectClick = {}, + onNotificationTabClick = {}, + onProfileTabClick = {}, + onNotificationSettingsClick = {}, + onProjectStatusClick = {}, + onSelfIntroductionClick = {}, + onPersonalInfoClick = {} + ) + } +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsRoute.kt new file mode 100644 index 0000000..2e3c202 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsRoute.kt @@ -0,0 +1,16 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.runtime.Composable + +@Composable +fun NotificationSettingsRoute( + onBackClick: () -> Unit, + onVersionInfoClick: () -> Unit, + onSignOutClick: () -> Unit +) { + NotificationSettingsScreen( + onBackClick = onBackClick, + onVersionInfoClick = onVersionInfoClick, + onSignOutClick = onSignOutClick + ) +} diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt new file mode 100644 index 0000000..fb458c1 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt @@ -0,0 +1,313 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +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.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Switch +import androidx.compose.material3.SwitchDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +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.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +@Composable +fun NotificationSettingsScreen( + onBackClick: () -> Unit, + onVersionInfoClick: () -> Unit, + onSignOutClick: () -> Unit, + modifier: Modifier = Modifier +) { + var projectNoticeEnabled by rememberSaveable { mutableStateOf(true) } + var applicationNoticeEnabled by rememberSaveable { mutableStateOf(true) } + var messageNoticeEnabled by rememberSaveable { mutableStateOf(true) } + var marketingNoticeEnabled by rememberSaveable { mutableStateOf(false) } + var showSignOutDialog by rememberSaveable { mutableStateOf(false) } + + if (showSignOutDialog) { + AlertDialog( + onDismissRequest = { showSignOutDialog = false }, + title = { + Text( + text = "로그아웃", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp + ) + }, + text = { + Text( + text = "정말 로그아웃하시겠습니까?", + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp + ) + }, + confirmButton = { + Text( + text = "로그아웃", + modifier = Modifier.clickable { + showSignOutDialog = false + onSignOutClick() + }, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = ItdaHomeExploreButtonGray + ) + }, + dismissButton = { + Text( + text = "취소", + modifier = Modifier.clickable { showSignOutDialog = false }, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + color = ItdaSecondaryTextColor + ) + }, + containerColor = ItdaWhite + ) + } + + Column( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + .padding(horizontal = 24.dp) + ) { + NotificationSettingsTopBar(onBackClick = onBackClick) + + Spacer(modifier = Modifier.height(22.dp)) + + SettingItem( + title = "프로젝트 알림", + description = "프로젝트 참여/변경 관련 알림을 받습니다.", + enabled = projectNoticeEnabled, + onCheckedChange = { projectNoticeEnabled = it } + ) + + SettingItem( + title = "지원 내역 알림", + description = "지원 결과와 상태 변경 알림을 받습니다.", + enabled = applicationNoticeEnabled, + onCheckedChange = { applicationNoticeEnabled = it } + ) + + SettingItem( + title = "메시지 알림", + description = "새 메시지 도착 시 알림을 받습니다.", + enabled = messageNoticeEnabled, + onCheckedChange = { messageNoticeEnabled = it } + ) + + SettingItem( + title = "마케팅 알림", + description = "이벤트, 신규 기능 안내를 받습니다.", + enabled = marketingNoticeEnabled, + onCheckedChange = { marketingNoticeEnabled = it } + ) + + Spacer(modifier = Modifier.height(4.dp)) + VersionInfoMenuItem(onClick = onVersionInfoClick) + + Spacer(modifier = Modifier.height(10.dp)) + LogoutMenuItem(onClick = { showSignOutDialog = true }) + } +} + +@Composable +private fun NotificationSettingsTopBar(onBackClick: () -> Unit) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(72.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(36.dp) + .clickable(onClick = onBackClick), + contentAlignment = Alignment.Center + ) { + Text( + text = "<", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + + Text( + text = "알림 설정", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 23.sp, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(start = 8.dp) + ) + } +} + +@Composable +private fun SettingItem( + title: String, + description: String, + enabled: Boolean, + onCheckedChange: (Boolean) -> Unit +) { + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 10.dp), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 14.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = description, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 12.sp, + lineHeight = 16.sp, + color = ItdaSecondaryTextColor + ) + } + + Switch( + checked = enabled, + onCheckedChange = onCheckedChange, + colors = SwitchDefaults.colors( + checkedThumbColor = ItdaWhite, + checkedTrackColor = ItdaHomeExploreButtonGray, + uncheckedThumbColor = ItdaWhite, + uncheckedTrackColor = Color(0xFFCCCCCC) + ) + ) + } + } +} + +@Composable +private fun VersionInfoMenuItem(onClick: () -> Unit) { + Surface( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "버전 정보", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onBackground + ) + + Text( + text = ">", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = ItdaSecondaryTextColor + ) + } + } +} + +@Composable +private fun LogoutMenuItem(onClick: () -> Unit) { + Surface( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 14.dp, vertical = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "로그아웃", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun NotificationSettingsScreenPreview() { + ITDATheme { + NotificationSettingsScreen( + onBackClick = {}, + onVersionInfoClick = {}, + onSignOutClick = {} + ) + } +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoRoute.kt new file mode 100644 index 0000000..2979de5 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoRoute.kt @@ -0,0 +1,11 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.runtime.Composable + +@Composable +fun PersonalInfoRoute( + onBackClick: () -> Unit +) { + PersonalInfoScreen(onBackClick = onBackClick) +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt new file mode 100644 index 0000000..7e941d7 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt @@ -0,0 +1,166 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.background +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.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +@Composable +fun PersonalInfoScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier +) { + var name by rememberSaveable { mutableStateOf("메타몽") } + var department by rememberSaveable { mutableStateOf("SW개발과") } + var grade by rememberSaveable { mutableStateOf("1학년") } + var joinDate by rememberSaveable { mutableStateOf("2025년 1월") } + + Column( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + .padding(horizontal = 24.dp) + ) { + PersonalInfoTopBar(onBackClick = onBackClick) + Spacer(modifier = Modifier.height(20.dp)) + + PersonalField("이름", name) { name = it } + Spacer(modifier = Modifier.height(12.dp)) + PersonalField("학과", department) { department = it } + Spacer(modifier = Modifier.height(12.dp)) + PersonalField("학년", grade) { grade = it } + Spacer(modifier = Modifier.height(12.dp)) + PersonalField("가입일", joinDate) { joinDate = it } + + Spacer(modifier = Modifier.height(18.dp)) + + Surface( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + .clickable(onClick = onBackClick), + shape = RoundedCornerShape(12.dp), + color = ItdaHomeExploreButtonGray + ) { + Box(contentAlignment = Alignment.Center) { + Text( + text = "저장", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = ItdaWhite + ) + } + } + } +} + +@Composable +private fun PersonalField( + label: String, + value: String, + onValueChange: (String) -> Unit +) { + Column { + Text( + text = label, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Spacer(modifier = Modifier.height(6.dp)) + OutlinedTextField( + value = value, + onValueChange = onValueChange, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(10.dp), + textStyle = MaterialTheme.typography.bodyMedium.copy(fontFamily = DotSans), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = ItdaGuideGray, + unfocusedBorderColor = ItdaGuideGray, + unfocusedTextColor = MaterialTheme.colorScheme.onBackground, + focusedTextColor = MaterialTheme.colorScheme.onBackground + ) + ) + } +} + +@Composable +private fun PersonalInfoTopBar( + onBackClick: () -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(72.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(36.dp) + .clickable(onClick = onBackClick), + contentAlignment = Alignment.Center + ) { + Text( + text = "<", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + + Text( + text = "개인 정보 입력", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 23.sp, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(start = 8.dp) + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun PersonalInfoScreenPreview() { + ITDATheme { + PersonalInfoScreen(onBackClick = {}) + } +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileRoute.kt new file mode 100644 index 0000000..9d1b12f --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileRoute.kt @@ -0,0 +1,25 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.runtime.Composable + +// Connects profile screen callbacks with navigation from the graph. +@Composable +fun ProfileRoute( + onHomeTabClick: () -> Unit, + onNotificationSettingsClick: () -> Unit, + onProjectStatusClick: () -> Unit, + onSelfIntroductionClick: () -> Unit, + onPersonalInfoClick: () -> Unit +) { + MyProfileScreen( + onHomeTabClick = onHomeTabClick, + onExploreTabClick = {}, + onCreateProjectClick = {}, + onNotificationTabClick = {}, + onProfileTabClick = {}, + onNotificationSettingsClick = onNotificationSettingsClick, + onProjectStatusClick = onProjectStatusClick, + onSelfIntroductionClick = onSelfIntroductionClick, + onPersonalInfoClick = onPersonalInfoClick + ) +} diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt new file mode 100644 index 0000000..fc1139a --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt @@ -0,0 +1,296 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.background +import androidx.compose.foundation.BorderStroke +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.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +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.it_da.ui.component.ItdaOutlinedBadge +import com.example.it_da.ui.screen.home.component.HomeBottomNavigationBar +import com.example.it_da.ui.screen.signup.component.SignUpTopBar +import com.example.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +// Shows the profile page matching the Figma structure with summary, stacks, and activity cards. +@Composable +fun ProfileScreen( + onHomeTabClick: () -> Unit, + onExploreTabClick: () -> Unit, + onCreateProjectClick: () -> Unit, + onNotificationTabClick: () -> Unit, + onProfileTabClick: () -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + ) { + Column( + modifier = Modifier.fillMaxSize() + ) { + SignUpTopBar(title = "Project") + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .padding(top = 22.dp, bottom = 84.dp) + ) { + ProfileHeader() + Spacer(modifier = Modifier.height(26.dp)) + + ProfileSectionTitle(text = "기술 스택") + Spacer(modifier = Modifier.height(14.dp)) + Row( + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + ItdaOutlinedBadge(text = "Back-end") + ItdaOutlinedBadge(text = "Java") + ItdaOutlinedBadge(text = "JavaScript") + ItdaOutlinedBadge(text = "Design") + } + + Spacer(modifier = Modifier.height(24.dp)) + ProfileSectionTitle(text = "경력") + Spacer(modifier = Modifier.height(10.dp)) + EmptyProfileBox(height = 86.dp) + + Spacer(modifier = Modifier.height(20.dp)) + ProfileSectionTitle(text = "자기 소개") + Spacer(modifier = Modifier.height(10.dp)) + EmptyProfileBox(height = 90.dp) + + Spacer(modifier = Modifier.height(20.dp)) + ProfileSectionTitle(text = "활동 요약") + Spacer(modifier = Modifier.height(12.dp)) + ActivitySummaryRow() + + Spacer(modifier = Modifier.height(12.dp)) + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + ActionButton( + text = "프로젝트 전체 보기", + modifier = Modifier.weight(1.35f) + ) + ActionButton( + text = "설정", + modifier = Modifier.weight(1f) + ) + } + } + } + + HomeBottomNavigationBar( + onHomeClick = onHomeTabClick, + onExploreClick = onExploreTabClick, + onCreateProjectClick = onCreateProjectClick, + onNotificationClick = onNotificationTabClick, + onProfileClick = onProfileTabClick, + modifier = Modifier + .align(Alignment.BottomCenter) + .navigationBarsPadding() + ) + } +} + +@Composable +private fun ProfileHeader() { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Surface( + modifier = Modifier.size(92.dp), + shape = CircleShape, + color = Color(0xFFE3E3E3) + ) { + Box(contentAlignment = Alignment.Center) { + Surface( + modifier = Modifier.size(38.dp), + shape = CircleShape, + color = Color(0xFF8F8F8F) + ) {} + } + } + + Spacer(modifier = Modifier.size(20.dp)) + + Column { + Text( + text = "메타몽", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 35.sp, + lineHeight = 40.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Text( + text = "SW개발과 · 1학년", + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 23.sp, + lineHeight = 26.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Text( + text = "가입일 2025년 1월", + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 23.sp, + lineHeight = 26.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + } +} + +@Composable +private fun ProfileSectionTitle(text: String) { + Text( + text = text, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 27.sp, + lineHeight = 31.sp, + color = MaterialTheme.colorScheme.onBackground + ) +} + +@Composable +private fun EmptyProfileBox(height: androidx.compose.ui.unit.Dp) { + Surface( + modifier = Modifier + .fillMaxWidth() + .height(height), + shape = RoundedCornerShape(12.dp), + color = Color.Transparent, + border = BorderStroke(1.2.dp, ItdaGuideGray) + ) {} +} + +@Composable +private fun ActivitySummaryRow() { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + ActivitySummaryCard( + value = "2", + label = "참여 프로젝트", + modifier = Modifier.weight(1f) + ) + ActivitySummaryCard( + value = "3", + label = "지원 내역", + modifier = Modifier.weight(1f) + ) + ActivitySummaryCard( + value = "1", + label = "받은 제안", + modifier = Modifier.weight(1f) + ) + } +} + +@Composable +private fun ActivitySummaryCard( + value: String, + label: String, + modifier: Modifier = Modifier +) { + Surface( + modifier = modifier.height(72.dp), + shape = RoundedCornerShape(12.dp), + color = Color.Transparent, + border = BorderStroke(1.2.dp, ItdaGuideGray) + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = value, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 17.sp, + lineHeight = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Spacer(modifier = Modifier.height(3.dp)) + Text( + text = label, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 11.sp, + lineHeight = 13.sp, + color = ItdaSecondaryTextColor + ) + } + } +} + +@Composable +private fun ActionButton( + text: String, + modifier: Modifier = Modifier +) { + Surface( + modifier = modifier.height(50.dp), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.2.dp, ItdaGuideGray) + ) { + Box(contentAlignment = Alignment.Center) { + Text( + text = text, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 16.sp, + color = ItdaSecondaryTextColor + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun ProfileScreenPreview() { + ITDATheme { + ProfileScreen( + onHomeTabClick = {}, + onExploreTabClick = {}, + onCreateProjectClick = {}, + onNotificationTabClick = {}, + onProfileTabClick = {} + ) + } +} diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusRoute.kt new file mode 100644 index 0000000..1b5ad3c --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusRoute.kt @@ -0,0 +1,11 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.runtime.Composable + +@Composable +fun ProjectStatusRoute( + onBackClick: () -> Unit +) { + ProjectStatusScreen(onBackClick = onBackClick) +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt new file mode 100644 index 0000000..6ab88c7 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt @@ -0,0 +1,228 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +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.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +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.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +private enum class ProjectFilter(val label: String) { + Participating("참여 중"), + Applied("지원 내역"), + Finished("완료") +} + +private data class ProjectStatusUiModel( + val title: String, + val description: String, + val status: String +) + +@Composable +fun ProjectStatusScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier +) { + var selectedFilter by rememberSaveable { mutableStateOf(ProjectFilter.Participating) } + + Column( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + .padding(horizontal = 24.dp) + ) { + ProjectStatusTopBar(onBackClick = onBackClick) + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + ProjectFilter.values().forEach { filter -> + FilterChip( + text = filter.label, + selected = selectedFilter == filter, + onClick = { selectedFilter = filter }, + modifier = Modifier.weight(1f) + ) + } + } + + Spacer(modifier = Modifier.height(14.dp)) + + LazyColumn( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items(statusItems(selectedFilter)) { item -> + ProjectStatusCard(item = item) + } + } + } +} + +@Composable +private fun ProjectStatusTopBar( + onBackClick: () -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(72.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(36.dp) + .clickable(onClick = onBackClick), + contentAlignment = Alignment.Center + ) { + Text( + text = "<", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + + Text( + text = "프로젝트 현황", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 23.sp, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(start = 8.dp) + ) + } +} + +@Composable +private fun FilterChip( + text: String, + selected: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + Surface( + modifier = modifier + .height(38.dp) + .clickable(onClick = onClick), + shape = RoundedCornerShape(22.dp), + color = if (selected) ItdaHomeExploreButtonGray else ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) + ) { + Box(contentAlignment = Alignment.Center) { + Text( + text = text, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 13.sp, + color = if (selected) ItdaWhite else ItdaSecondaryTextColor + ) + } + } +} + +@Composable +private fun ProjectStatusCard(item: ProjectStatusUiModel) { + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) + ) { + Column(modifier = Modifier.padding(horizontal = 14.dp, vertical = 14.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = item.title, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Text( + text = item.status, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 12.sp, + color = ItdaSecondaryTextColor + ) + } + Spacer(modifier = Modifier.height(6.dp)) + Text( + text = item.description, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 13.sp, + color = ItdaSecondaryTextColor + ) + } + } +} + +private fun statusItems(filter: ProjectFilter): List { + return when (filter) { + ProjectFilter.Participating -> listOf( + ProjectStatusUiModel("IT-DA Android", "프로필/설정 화면 구현 진행 중", "진행중"), + ProjectStatusUiModel("캡스톤 매칭 서비스", "백엔드 API 연동 작업 진행", "진행중") + ) + + ProjectFilter.Applied -> listOf( + ProjectStatusUiModel("AI 일정 도우미", "서류 심사 결과 대기 중", "대기"), + ProjectStatusUiModel("스터디 팀빌딩", "인터뷰 일정 조율 중", "검토중") + ) + + ProjectFilter.Finished -> listOf( + ProjectStatusUiModel("학교 축제 웹", "프론트엔드 구현 담당 완료", "완료"), + ProjectStatusUiModel("동아리 홈페이지", "유지보수 배포까지 완료", "완료") + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun ProjectStatusScreenPreview() { + ITDATheme { + ProjectStatusScreen(onBackClick = {}) + } +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionRoute.kt new file mode 100644 index 0000000..28961e4 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionRoute.kt @@ -0,0 +1,11 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.runtime.Composable + +@Composable +fun SelfIntroductionRoute( + onBackClick: () -> Unit +) { + SelfIntroductionScreen(onBackClick = onBackClick) +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt new file mode 100644 index 0000000..1313fc0 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt @@ -0,0 +1,221 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +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.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +@Composable +fun SelfIntroductionScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier +) { + var introduction by rememberSaveable { + mutableStateOf("안녕하세요. 사용자 경험을 중요하게 생각하는 안드로이드 개발자입니다.") + } + var draftIntroduction by rememberSaveable { mutableStateOf(introduction) } + var showEditDialog by rememberSaveable { mutableStateOf(false) } + + if (showEditDialog) { + AlertDialog( + onDismissRequest = { showEditDialog = false }, + title = { + Text( + text = "자기소개 수정", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp + ) + }, + text = { + OutlinedTextField( + value = draftIntroduction, + onValueChange = { draftIntroduction = it }, + modifier = Modifier + .fillMaxWidth() + .height(170.dp), + placeholder = { + Text( + text = "자기소개를 입력해 주세요.", + fontFamily = DotSans, + color = ItdaSecondaryTextColor + ) + }, + shape = RoundedCornerShape(12.dp), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = ItdaGuideGray, + unfocusedBorderColor = ItdaGuideGray + ) + ) + }, + confirmButton = { + Text( + text = "저장", + modifier = Modifier.clickable { + introduction = draftIntroduction + showEditDialog = false + }, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = ItdaHomeExploreButtonGray + ) + }, + dismissButton = { + Text( + text = "취소", + modifier = Modifier.clickable { showEditDialog = false }, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + color = ItdaSecondaryTextColor + ) + }, + containerColor = ItdaWhite + ) + } + + Column( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + .padding(horizontal = 24.dp) + ) { + SelfIntroductionTopBar(onBackClick = onBackClick) + + Spacer(modifier = Modifier.height(20.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "자기소개", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 21.sp, + color = MaterialTheme.colorScheme.onBackground + ) + + Surface( + modifier = Modifier.clickable { + draftIntroduction = introduction + showEditDialog = true + }, + shape = RoundedCornerShape(10.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray) + ) { + Text( + text = "수정하기", + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 13.sp, + color = ItdaSecondaryTextColor + ) + } + } + + Spacer(modifier = Modifier.height(10.dp)) + + Surface( + modifier = Modifier + .fillMaxWidth() + .height(220.dp), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray) + ) { + Text( + text = introduction, + modifier = Modifier.padding(14.dp), + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 15.sp, + lineHeight = 22.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + } +} + +@Composable +private fun SelfIntroductionTopBar(onBackClick: () -> Unit) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(72.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(36.dp) + .clickable(onClick = onBackClick), + contentAlignment = Alignment.Center + ) { + Text( + text = "<", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + + Text( + text = "자기소개 작성", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 23.sp, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(start = 8.dp) + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun SelfIntroductionScreenPreview() { + ITDATheme { + SelfIntroductionScreen(onBackClick = {}) + } +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoRoute.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoRoute.kt new file mode 100644 index 0000000..8ab9e43 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoRoute.kt @@ -0,0 +1,11 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.runtime.Composable + +@Composable +fun VersionInfoRoute( + onBackClick: () -> Unit +) { + VersionInfoScreen(onBackClick = onBackClick) +} + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt new file mode 100644 index 0000000..cf17edd --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt @@ -0,0 +1,138 @@ +package com.example.it_da.ui.screen.profile + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +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.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import com.example.it_da.BuildConfig +import com.example.it_da.ui.theme.DotSans +import com.example.it_da.ui.theme.ItdaGuideGray +import com.example.it_da.ui.theme.ItdaSecondaryTextColor +import com.example.it_da.ui.theme.ItdaWhite +import com.example.it_da.ui.theme.ITDATheme + +@Composable +fun VersionInfoScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + .statusBarsPadding() + .padding(horizontal = 24.dp) + ) { + VersionTopBar(onBackClick = onBackClick) + + Spacer(modifier = Modifier.height(26.dp)) + + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(12.dp), + color = ItdaWhite, + border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) + ) { + Column( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 16.dp), + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + VersionRow(label = "현재 버전", value = BuildConfig.VERSION_NAME) + VersionRow(label = "버전 코드", value = BuildConfig.VERSION_CODE.toString()) + } + } + } +} + +@Composable +private fun VersionTopBar( + onBackClick: () -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .height(72.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .size(36.dp) + .clickable(onClick = onBackClick), + contentAlignment = Alignment.Center + ) { + Text( + text = "<", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + + Text( + text = "버전 정보", + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 23.sp, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(start = 8.dp) + ) + } +} + +@Composable +private fun VersionRow( + label: String, + value: String +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = label, + fontFamily = DotSans, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onBackground + ) + Text( + text = value, + fontFamily = DotSans, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + color = ItdaSecondaryTextColor + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun VersionInfoScreenPreview() { + ITDATheme { + VersionInfoScreen(onBackClick = {}) + } +} + From d969e5fe607f343f90168072963f3e26d5090a9d Mon Sep 17 00:00:00 2001 From: soyuo Date: Wed, 27 May 2026 17:28:29 +0900 Subject: [PATCH 3/4] =?UTF-8?q?chore(ui):=20=ED=99=88=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=20=EB=9D=BC=EB=B2=A8=20=EB=B0=8F=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=AC=B8=EA=B5=AC=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../it_da/ui/screen/home/HomeScreen.kt | 38 +++++++++---------- .../home/component/HomeBottomNavigationBar.kt | 16 ++++---- .../signup/component/SignUpPrimaryButton.kt | 4 +- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/home/HomeScreen.kt index ff9a4e6..1c3cd18 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/HomeScreen.kt @@ -19,22 +19,21 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.it_da.R -import com.example.it_da.ui.screen.home.component.HomeBottomNavigationBar import com.example.it_da.ui.component.section.HomeNotificationSection import com.example.it_da.ui.component.section.HomeProfileSummarySection import com.example.it_da.ui.component.section.ParticipatingProjectSection import com.example.it_da.ui.component.section.RecommendedProjectSection -import com.example.it_da.ui.screen.signup.component.SignUpPrimaryButton -import com.example.it_da.ui.screen.signup.component.SignUpTopBar +import com.example.it_da.ui.screen.home.component.HomeBottomNavigationBar import com.example.it_da.ui.screen.home.state.HomeNotificationUiModel import com.example.it_da.ui.screen.home.state.HomeProjectCountUiModel import com.example.it_da.ui.screen.home.state.HomeUiState import com.example.it_da.ui.screen.home.state.ParticipatingProjectUiModel import com.example.it_da.ui.screen.home.state.RecommendedProjectUiModel -import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray +import com.example.it_da.ui.screen.signup.component.SignUpPrimaryButton +import com.example.it_da.ui.screen.signup.component.SignUpTopBar import com.example.it_da.ui.theme.ITDATheme +import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray -// Assembles the home screen from state-driven sections and button callbacks. @Composable fun HomeScreen( uiState: HomeUiState, @@ -87,7 +86,6 @@ fun HomeScreen( } } -// Lays out the scrollable home content while the bottom navigation remains fixed. @Composable private fun HomeContent( uiState: HomeUiState, @@ -173,12 +171,11 @@ private fun HomeScreenPreview() { } } -// Supplies preview-only values so the screen can be checked without the ViewModel. private fun previewHomeUiState(): HomeUiState { return HomeUiState( - userName = "000", + userName = "메타몽", profileImageResId = R.drawable.home_profile_placeholder, - greetingDescription = "상상은 여기서 현실이 됩니다.\n당신의 프로젝트와 팀을 찾아보세요", + greetingDescription = "오늘도 멋진 하루예요.\n딱 맞는 프로젝트를 찾아보세요!", projectCount = HomeProjectCountUiModel( applyingCount = 3, participatingCount = 1, @@ -187,38 +184,39 @@ private fun previewHomeUiState(): HomeUiState { recommendedProjects = listOf( RecommendedProjectUiModel( id = "recommended-ai-planner", - title = "AI 기반 학습 플래너 [0부0부]", + title = "AI 기반 학습 플래너", recruitingSummary = "백엔드 개발자 1명 모집", statusText = "모집 중", techStacks = listOf("Back-end"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT공학 2명, SW공학 1명 참여" ), RecommendedProjectUiModel( id = "recommended-pokemon", - title = "닮은 포켓몬 검사 [포켓몬백]", - recruitingSummary = "iOS 개발자ㆍ1명ㆍ디자이너 1명 모집", + title = "포켓몬 도감 검색 앱", + recruitingSummary = "iOS 개발 1명, 디자이너 1명 모집", statusText = "마감 임박", techStacks = listOf("iOS", "Design"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT공학 2명, SW공학 1명 참여" ) ), participatingProjects = listOf( ParticipatingProjectUiModel( id = "participating-dalbal", - title = "사랑을 이어주는 앱 [달발]", - myRole = "내 역할 : iOS 개발", + title = "달려서 케어해주는 앱", + myRole = "내 역할: iOS 개발", statusText = "진행 중", - teamSummary = "팀원 4명ㆍ마감 2026-05-31" + teamSummary = "총 4명, 마감 2026-05-31" ) ), notifications = listOf( HomeNotificationUiModel( id = "notification-message", imageResId = R.drawable.home_notification_mailbox, - imageDescription = "새 메시지 알림", - message = "지원한 프로젝트에서 새 메시지가 있습니다", - elapsedTime = "2분전" + imageDescription = "메시지 알림", + message = "진행 중인 프로젝트에서 새 메시지가 도착했습니다.", + elapsedTime = "2분 전" ) ) ) } + diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeBottomNavigationBar.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeBottomNavigationBar.kt index 08538cf..28e4208 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeBottomNavigationBar.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeBottomNavigationBar.kt @@ -35,7 +35,6 @@ private val HomeBottomNavigationBarHeight = 52.5.dp private val HomeBottomNavigationContainerHeight = 62.dp private val HomeBottomNavigationItemHeight = 48.dp -// Shows the fixed bottom navigation bar and exposes each tab as a callback. @Composable fun HomeBottomNavigationBar( onHomeClick: () -> Unit, @@ -66,7 +65,7 @@ fun HomeBottomNavigationBar( HomeBottomNavigationItem( iconResId = R.drawable.bottom_bar_home, label = "홈", - contentDescription = "홈", + contentDescription = "홈 탭", iconSize = 25.dp, onClick = onHomeClick ) @@ -74,7 +73,7 @@ fun HomeBottomNavigationBar( HomeBottomNavigationItem( iconResId = R.drawable.bottom_bar_research, label = "탐색", - contentDescription = "탐색", + contentDescription = "탐색 탭", iconSize = 25.dp, onClick = onExploreClick ) @@ -88,15 +87,15 @@ fun HomeBottomNavigationBar( HomeBottomNavigationItem( iconResId = R.drawable.bottom_bar_bell, label = "알림", - contentDescription = "알림", + contentDescription = "알림 탭", iconSize = 25.dp, onClick = onNotificationClick ) HomeBottomNavigationItem( iconResId = R.drawable.bottom_bar_profile, - label = "프로필", - contentDescription = "프로필", + label = "My", + contentDescription = "내 프로필 탭", iconSize = 25.dp, onClick = onProfileClick ) @@ -110,7 +109,6 @@ fun HomeBottomNavigationBar( } } -// Shows a normal labeled bottom navigation item. @Composable private fun HomeBottomNavigationItem( @DrawableRes iconResId: Int, @@ -148,7 +146,6 @@ private fun HomeBottomNavigationItem( } } -// Shows the center add-project action as the prominent middle bottom button. @Composable private fun HomeCenterNavigationButton( onClick: () -> Unit, @@ -157,7 +154,7 @@ private fun HomeCenterNavigationButton( Box( modifier = modifier .size(45.dp) - .clip(androidx.compose.foundation.shape.RoundedCornerShape(12.dp)) + .clip(RoundedCornerShape(12.dp)) .clickable(onClick = onClick), contentAlignment = Alignment.Center ) { @@ -168,3 +165,4 @@ private fun HomeCenterNavigationButton( ) } } + diff --git a/app/src/main/java/com/example/it_da/ui/screen/signup/component/SignUpPrimaryButton.kt b/app/src/main/java/com/example/it_da/ui/screen/signup/component/SignUpPrimaryButton.kt index 3bc517c..d2a06db 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/signup/component/SignUpPrimaryButton.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/signup/component/SignUpPrimaryButton.kt @@ -16,12 +16,11 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.example.it_da.ui.theme.ItdaLoginButtonDisabledBlack import com.example.it_da.ui.theme.ItdaButtonTextColor +import com.example.it_da.ui.theme.ItdaLoginButtonDisabledBlack private val SignUpPrimaryButtonTextWeight = FontWeight(600) -// Shows the sign-up primary action and lets Button enforce the enabled click rule. @Composable fun SignUpPrimaryButton( enabled: Boolean, @@ -60,3 +59,4 @@ fun SignUpPrimaryButton( } } } + From 6bbd4c1cfc76539dbe56b353d196a7df1734d54d Mon Sep 17 00:00:00 2001 From: soyuo Date: Sat, 30 May 2026 19:54:16 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor(profile):=20=EC=8A=A4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=84=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/screen/profile/MyProfileScreen.kt | 132 +++++++---- .../profile/NotificationSettingsScreen.kt | 187 +++++---------- .../ui/screen/profile/PersonalInfoScreen.kt | 81 ++----- .../it_da/ui/screen/profile/ProfileScreen.kt | 218 +++++------------- .../ui/screen/profile/ProjectStatusScreen.kt | 86 ++----- .../screen/profile/SelfIntroductionScreen.kt | 81 ++----- .../ui/screen/profile/VersionInfoScreen.kt | 71 ++---- 7 files changed, 290 insertions(+), 566 deletions(-) diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt index 5d26dec..be7aad3 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/MyProfileScreen.kt @@ -7,7 +7,6 @@ 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 @@ -38,6 +37,21 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme +private val ProfileOuterHorizontalPadding = 24.dp +private val ProfileOuterTopPadding = 22.dp +private val ProfileOuterBottomPadding = 84.dp +private val ProfileSectionLargeSpacing = 24.dp +private val ProfileSectionMediumSpacing = 20.dp +private val ProfileTitleToContentSpacing = 10.dp +private val ProfileHeaderToButtonSpacing = 14.dp +private val ProfileButtonToFirstSectionSpacing = 22.dp +private val ProfileSummaryTopSpacing = 12.dp +private val ProfileActionRowTopSpacing = 12.dp +private val ProfileChipSpacing = 6.dp +private val ProfileCardRowSpacing = 12.dp +private val ProfileHeaderAvatarTextSpacing = 20.dp +private val ProfileHeaderTextSpacing = 2.dp + @Composable fun MyProfileScreen( onHomeTabClick: () -> Unit, @@ -63,65 +77,69 @@ fun MyProfileScreen( Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 24.dp) - .padding(top = 22.dp, bottom = 84.dp) + .padding(horizontal = ProfileOuterHorizontalPadding) + .padding(top = ProfileOuterTopPadding, bottom = ProfileOuterBottomPadding), + verticalArrangement = Arrangement.spacedBy(ProfileSectionMediumSpacing) ) { MyProfileHeader() - Spacer(modifier = Modifier.height(14.dp)) ActionButton( text = "개인 정보 입력", onClick = onPersonalInfoClick ) - Spacer(modifier = Modifier.height(22.dp)) - SectionTitle(text = "기술 스택") - Spacer(modifier = Modifier.height(14.dp)) - Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) { - ItdaOutlinedBadge(text = "Back-end") - ItdaOutlinedBadge(text = "Java") - ItdaOutlinedBadge(text = "JavaScript") - ItdaOutlinedBadge(text = "Design") + SectionBlock( + title = "기술 스택", + titleToContentSpacing = ProfileHeaderToButtonSpacing + ) { + Row(horizontalArrangement = Arrangement.spacedBy(ProfileChipSpacing)) { + ItdaOutlinedBadge(text = "Back-end") + ItdaOutlinedBadge(text = "Java") + ItdaOutlinedBadge(text = "JavaScript") + ItdaOutlinedBadge(text = "Design") + } } - Spacer(modifier = Modifier.height(24.dp)) - SectionTitle(text = "경력") - Spacer(modifier = Modifier.height(10.dp)) - EmptyBox(height = 86.dp) + SectionBlock(title = "경력") { + EmptyBox(height = 86.dp) + } - Spacer(modifier = Modifier.height(20.dp)) - SectionTitle(text = "자기 소개") - Spacer(modifier = Modifier.height(10.dp)) - EmptyBox( - height = 90.dp, - text = "자기소개 작성하기", - onClick = onSelfIntroductionClick - ) + SectionBlock(title = "자기 소개") { + EmptyBox( + height = 90.dp, + text = "자기소개 작성하기", + onClick = onSelfIntroductionClick + ) + } - Spacer(modifier = Modifier.height(20.dp)) - SectionTitle(text = "활동 요약") - Spacer(modifier = Modifier.height(12.dp)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(12.dp) + Column( + verticalArrangement = Arrangement.spacedBy(ProfileSummaryTopSpacing) ) { - SummaryCard(value = "2", label = "참여 프로젝트", modifier = Modifier.weight(1f)) - SummaryCard(value = "3", label = "지원 내역", modifier = Modifier.weight(1f)) - SummaryCard(value = "1", label = "받은 제안", modifier = Modifier.weight(1f)) - } + SectionTitle(text = "활동 요약") - Spacer(modifier = Modifier.height(12.dp)) - Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { - ActionButton( - text = "프로젝트 전체 보기", - modifier = Modifier.weight(1.35f), - onClick = onProjectStatusClick - ) - ActionButton( - text = "설정", - modifier = Modifier.weight(1f), - onClick = onNotificationSettingsClick - ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(ProfileCardRowSpacing) + ) { + SummaryCard(value = "2", label = "참여 프로젝트", modifier = Modifier.weight(1f)) + SummaryCard(value = "3", label = "지원 내역", modifier = Modifier.weight(1f)) + SummaryCard(value = "1", label = "받은 제안", modifier = Modifier.weight(1f)) + } + + Row( + horizontalArrangement = Arrangement.spacedBy(ProfileCardRowSpacing) + ) { + ActionButton( + text = "프로젝트 전체 보기", + modifier = Modifier.weight(1.35f), + onClick = onProjectStatusClick + ) + ActionButton( + text = "설정", + modifier = Modifier.weight(1f), + onClick = onNotificationSettingsClick + ) + } } } } @@ -139,11 +157,26 @@ fun MyProfileScreen( } } +@Composable +private fun SectionBlock( + title: String, + titleToContentSpacing: Dp = ProfileTitleToContentSpacing, + content: @Composable () -> Unit +) { + Column( + verticalArrangement = Arrangement.spacedBy(titleToContentSpacing) + ) { + SectionTitle(text = title) + content() + } +} + @Composable private fun MyProfileHeader() { Row( modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(ProfileHeaderAvatarTextSpacing) ) { Surface( modifier = Modifier.size(92.dp), @@ -159,9 +192,7 @@ private fun MyProfileHeader() { } } - Spacer(modifier = Modifier.size(20.dp)) - - Column { + Column(verticalArrangement = Arrangement.spacedBy(ProfileHeaderTextSpacing)) { Text( text = "메타몽", fontFamily = DotSans, @@ -258,7 +289,6 @@ private fun SummaryCard( lineHeight = 20.sp, color = MaterialTheme.colorScheme.onBackground ) - Spacer(modifier = Modifier.height(3.dp)) Text( text = label, fontFamily = DotSans, diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt index fb458c1..5f74fc7 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/NotificationSettingsScreen.kt @@ -7,7 +7,6 @@ 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 @@ -40,6 +39,14 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme +private val SettingsHorizontalPadding = 24.dp +private val SettingsTopSpacing = 22.dp +private val SettingsSectionSpacing = 10.dp +private val SettingsMenuSpacing = 4.dp +private val SettingsItemInnerVertical = 14.dp +private val SettingsItemInnerHorizontal = 14.dp +private val SettingsDescriptionSpacing = 4.dp + @Composable fun NotificationSettingsScreen( onBackClick: () -> Unit, @@ -57,20 +64,10 @@ fun NotificationSettingsScreen( AlertDialog( onDismissRequest = { showSignOutDialog = false }, title = { - Text( - text = "로그아웃", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp - ) + Text("로그아웃", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) }, text = { - Text( - text = "정말 로그아웃하시겠습니까?", - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 14.sp - ) + Text("정말 로그아웃하시겠습니까?", fontFamily = DotSans, fontSize = 14.sp) }, confirmButton = { Text( @@ -90,7 +87,6 @@ fun NotificationSettingsScreen( text = "취소", modifier = Modifier.clickable { showSignOutDialog = false }, fontFamily = DotSans, - fontWeight = FontWeight.Normal, fontSize = 14.sp, color = ItdaSecondaryTextColor ) @@ -104,78 +100,63 @@ fun NotificationSettingsScreen( .fillMaxSize() .background(MaterialTheme.colorScheme.background) .statusBarsPadding() - .padding(horizontal = 24.dp) + .padding(horizontal = SettingsHorizontalPadding), + verticalArrangement = Arrangement.spacedBy(SettingsSectionSpacing) ) { NotificationSettingsTopBar(onBackClick = onBackClick) - Spacer(modifier = Modifier.height(22.dp)) - - SettingItem( - title = "프로젝트 알림", - description = "프로젝트 참여/변경 관련 알림을 받습니다.", - enabled = projectNoticeEnabled, - onCheckedChange = { projectNoticeEnabled = it } - ) - - SettingItem( - title = "지원 내역 알림", - description = "지원 결과와 상태 변경 알림을 받습니다.", - enabled = applicationNoticeEnabled, - onCheckedChange = { applicationNoticeEnabled = it } - ) - - SettingItem( - title = "메시지 알림", - description = "새 메시지 도착 시 알림을 받습니다.", - enabled = messageNoticeEnabled, - onCheckedChange = { messageNoticeEnabled = it } - ) - - SettingItem( - title = "마케팅 알림", - description = "이벤트, 신규 기능 안내를 받습니다.", - enabled = marketingNoticeEnabled, - onCheckedChange = { marketingNoticeEnabled = it } - ) - - Spacer(modifier = Modifier.height(4.dp)) - VersionInfoMenuItem(onClick = onVersionInfoClick) + Column(verticalArrangement = Arrangement.spacedBy(SettingsSectionSpacing)) { + SettingItem( + title = "프로젝트 알림", + description = "프로젝트 참여/변경 관련 알림을 받습니다.", + enabled = projectNoticeEnabled, + onCheckedChange = { projectNoticeEnabled = it } + ) + SettingItem( + title = "지원 내역 알림", + description = "지원 결과와 상태 변경 알림을 받습니다.", + enabled = applicationNoticeEnabled, + onCheckedChange = { applicationNoticeEnabled = it } + ) + SettingItem( + title = "메시지 알림", + description = "새 메시지 도착 시 알림을 받습니다.", + enabled = messageNoticeEnabled, + onCheckedChange = { messageNoticeEnabled = it } + ) + SettingItem( + title = "마케팅 알림", + description = "이벤트, 신규 기능 안내를 받습니다.", + enabled = marketingNoticeEnabled, + onCheckedChange = { marketingNoticeEnabled = it } + ) + } - Spacer(modifier = Modifier.height(10.dp)) - LogoutMenuItem(onClick = { showSignOutDialog = true }) + Column(verticalArrangement = Arrangement.spacedBy(SettingsMenuSpacing)) { + VersionInfoMenuItem(onClick = onVersionInfoClick) + LogoutMenuItem(onClick = { showSignOutDialog = true }) + } } } @Composable private fun NotificationSettingsTopBar(onBackClick: () -> Unit) { Row( - modifier = Modifier - .fillMaxWidth() - .height(72.dp), + modifier = Modifier.fillMaxWidth().height(72.dp), verticalAlignment = Alignment.CenterVertically ) { Box( - modifier = Modifier - .size(36.dp) - .clickable(onClick = onBackClick), + modifier = Modifier.size(36.dp).clickable(onClick = onBackClick), contentAlignment = Alignment.Center ) { - Text( - text = "<", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Text("<", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) } - Text( text = "알림 설정", + modifier = Modifier.padding(start = 8.dp), fontFamily = DotSans, fontWeight = FontWeight.Bold, - fontSize = 23.sp, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.padding(start = 8.dp) + fontSize = 23.sp ) } } @@ -188,39 +169,30 @@ private fun SettingItem( onCheckedChange: (Boolean) -> Unit ) { Surface( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 10.dp), + modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), color = ItdaWhite, border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 14.dp, vertical = 14.dp), + modifier = Modifier.fillMaxWidth() + .padding(horizontal = SettingsItemInnerHorizontal, vertical = SettingsItemInnerVertical), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Column(modifier = Modifier.weight(1f)) { - Text( - text = title, - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Spacer(modifier = Modifier.height(4.dp)) + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(SettingsDescriptionSpacing) + ) { + Text(title, fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp) Text( text = description, fontFamily = DotSans, - fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = 16.sp, color = ItdaSecondaryTextColor ) } - Switch( checked = enabled, onCheckedChange = onCheckedChange, @@ -238,35 +210,18 @@ private fun SettingItem( @Composable private fun VersionInfoMenuItem(onClick: () -> Unit) { Surface( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick), + modifier = Modifier.fillMaxWidth().clickable(onClick = onClick), shape = RoundedCornerShape(12.dp), color = ItdaWhite, border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 14.dp, vertical = 16.dp), + modifier = Modifier.fillMaxWidth().padding(horizontal = 14.dp, vertical = 16.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( - text = "버전 정보", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = MaterialTheme.colorScheme.onBackground - ) - - Text( - text = ">", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = ItdaSecondaryTextColor - ) + Text("버전 정보", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp) + Text(">", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp, color = ItdaSecondaryTextColor) } } } @@ -274,27 +229,17 @@ private fun VersionInfoMenuItem(onClick: () -> Unit) { @Composable private fun LogoutMenuItem(onClick: () -> Unit) { Surface( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onClick), + modifier = Modifier.fillMaxWidth().clickable(onClick = onClick), shape = RoundedCornerShape(12.dp), color = ItdaWhite, border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 14.dp, vertical = 16.dp), + modifier = Modifier.fillMaxWidth().padding(horizontal = 14.dp, vertical = 16.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( - text = "로그아웃", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Text("로그아웃", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp) } } } @@ -302,12 +247,6 @@ private fun LogoutMenuItem(onClick: () -> Unit) { @Preview(showBackground = true) @Composable private fun NotificationSettingsScreenPreview() { - ITDATheme { - NotificationSettingsScreen( - onBackClick = {}, - onVersionInfoClick = {}, - onSignOutClick = {} - ) - } + ITDATheme { NotificationSettingsScreen(onBackClick = {}, onVersionInfoClick = {}, onSignOutClick = {}) } } diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt index 7e941d7..1188754 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/PersonalInfoScreen.kt @@ -6,7 +6,6 @@ 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 @@ -33,10 +32,14 @@ import androidx.compose.ui.unit.sp import com.example.it_da.ui.theme.DotSans import com.example.it_da.ui.theme.ItdaGuideGray import com.example.it_da.ui.theme.ItdaHomeExploreButtonGray -import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme +private val PersonalInfoHorizontalPadding = 24.dp +private val PersonalInfoSectionSpacing = 12.dp +private val PersonalInfoTopSpacing = 20.dp +private val PersonalInfoFieldSpacing = 6.dp + @Composable fun PersonalInfoScreen( onBackClick: () -> Unit, @@ -52,37 +55,25 @@ fun PersonalInfoScreen( .fillMaxSize() .background(MaterialTheme.colorScheme.background) .statusBarsPadding() - .padding(horizontal = 24.dp) + .padding(horizontal = PersonalInfoHorizontalPadding), + verticalArrangement = Arrangement.spacedBy(PersonalInfoSectionSpacing) ) { PersonalInfoTopBar(onBackClick = onBackClick) - Spacer(modifier = Modifier.height(20.dp)) - - PersonalField("이름", name) { name = it } - Spacer(modifier = Modifier.height(12.dp)) - PersonalField("학과", department) { department = it } - Spacer(modifier = Modifier.height(12.dp)) - PersonalField("학년", grade) { grade = it } - Spacer(modifier = Modifier.height(12.dp)) - PersonalField("가입일", joinDate) { joinDate = it } - Spacer(modifier = Modifier.height(18.dp)) + Column(verticalArrangement = Arrangement.spacedBy(PersonalInfoSectionSpacing)) { + PersonalField("이름", name) { name = it } + PersonalField("학과", department) { department = it } + PersonalField("학년", grade) { grade = it } + PersonalField("가입일", joinDate) { joinDate = it } + } Surface( - modifier = Modifier - .fillMaxWidth() - .height(48.dp) - .clickable(onClick = onBackClick), + modifier = Modifier.fillMaxWidth().height(48.dp).clickable(onClick = onBackClick), shape = RoundedCornerShape(12.dp), color = ItdaHomeExploreButtonGray ) { Box(contentAlignment = Alignment.Center) { - Text( - text = "저장", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = ItdaWhite - ) + Text("저장", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp, color = ItdaWhite) } } } @@ -94,15 +85,8 @@ private fun PersonalField( value: String, onValueChange: (String) -> Unit ) { - Column { - Text( - text = label, - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 14.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Spacer(modifier = Modifier.height(6.dp)) + Column(verticalArrangement = Arrangement.spacedBy(PersonalInfoFieldSpacing)) { + Text(label, fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 14.sp) OutlinedTextField( value = value, onValueChange = onValueChange, @@ -120,38 +104,23 @@ private fun PersonalField( } @Composable -private fun PersonalInfoTopBar( - onBackClick: () -> Unit -) { +private fun PersonalInfoTopBar(onBackClick: () -> Unit) { Row( - modifier = Modifier - .fillMaxWidth() - .height(72.dp), - horizontalArrangement = Arrangement.Start, + modifier = Modifier.fillMaxWidth().height(72.dp), verticalAlignment = Alignment.CenterVertically ) { Box( - modifier = Modifier - .size(36.dp) - .clickable(onClick = onBackClick), + modifier = Modifier.size(36.dp).clickable(onClick = onBackClick), contentAlignment = Alignment.Center ) { - Text( - text = "<", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Text("<", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) } - Text( text = "개인 정보 입력", + modifier = Modifier.padding(start = 8.dp), fontFamily = DotSans, fontWeight = FontWeight.Bold, - fontSize = 23.sp, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.padding(start = 8.dp) + fontSize = 23.sp ) } } @@ -159,8 +128,6 @@ private fun PersonalInfoTopBar( @Preview(showBackground = true) @Composable private fun PersonalInfoScreenPreview() { - ITDATheme { - PersonalInfoScreen(onBackClick = {}) - } + ITDATheme { PersonalInfoScreen(onBackClick = {}) } } diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt index fc1139a..543dc02 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/ProfileScreen.kt @@ -1,19 +1,17 @@ package com.example.it_da.ui.screen.profile -import androidx.compose.foundation.background import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background 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.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme @@ -25,6 +23,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color 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.dp import androidx.compose.ui.unit.sp import com.example.it_da.ui.component.ItdaOutlinedBadge @@ -36,7 +35,14 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme -// Shows the profile page matching the Figma structure with summary, stacks, and activity cards. +private val OtherProfileHorizontalPadding = 24.dp +private val OtherProfileOuterSpacing = 20.dp +private val OtherProfileTitleContentSpacing = 10.dp +private val OtherProfileChipSpacing = 6.dp +private val OtherProfileCardSpacing = 12.dp +private val OtherProfileHeaderSpacing = 20.dp +private val OtherProfileHeaderTextSpacing = 2.dp + @Composable fun ProfileScreen( onHomeTabClick: () -> Unit, @@ -50,60 +56,34 @@ fun ProfileScreen( modifier = modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background) - .statusBarsPadding() ) { - Column( - modifier = Modifier.fillMaxSize() - ) { + Column(modifier = Modifier.fillMaxSize()) { SignUpTopBar(title = "Project") - Column( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 24.dp) - .padding(top = 22.dp, bottom = 84.dp) + .padding(horizontal = OtherProfileHorizontalPadding) + .padding(top = 22.dp, bottom = 84.dp), + verticalArrangement = Arrangement.spacedBy(OtherProfileOuterSpacing) ) { ProfileHeader() - Spacer(modifier = Modifier.height(26.dp)) - - ProfileSectionTitle(text = "기술 스택") - Spacer(modifier = Modifier.height(14.dp)) - Row( - horizontalArrangement = Arrangement.spacedBy(6.dp) - ) { - ItdaOutlinedBadge(text = "Back-end") - ItdaOutlinedBadge(text = "Java") - ItdaOutlinedBadge(text = "JavaScript") - ItdaOutlinedBadge(text = "Design") + Section("기술 스택") { + Row(horizontalArrangement = Arrangement.spacedBy(OtherProfileChipSpacing)) { + ItdaOutlinedBadge(text = "Back-end") + ItdaOutlinedBadge(text = "Java") + ItdaOutlinedBadge(text = "JavaScript") + ItdaOutlinedBadge(text = "Design") + } } - - Spacer(modifier = Modifier.height(24.dp)) - ProfileSectionTitle(text = "경력") - Spacer(modifier = Modifier.height(10.dp)) - EmptyProfileBox(height = 86.dp) - - Spacer(modifier = Modifier.height(20.dp)) - ProfileSectionTitle(text = "자기 소개") - Spacer(modifier = Modifier.height(10.dp)) - EmptyProfileBox(height = 90.dp) - - Spacer(modifier = Modifier.height(20.dp)) - ProfileSectionTitle(text = "활동 요약") - Spacer(modifier = Modifier.height(12.dp)) - ActivitySummaryRow() - - Spacer(modifier = Modifier.height(12.dp)) - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - ActionButton( - text = "프로젝트 전체 보기", - modifier = Modifier.weight(1.35f) - ) - ActionButton( - text = "설정", - modifier = Modifier.weight(1f) - ) + Section("경력") { EmptyProfileBox(height = 86.dp) } + Section("자기 소개") { EmptyProfileBox(height = 90.dp) } + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + ProfileSectionTitle(text = "활동 요약") + ActivitySummaryRow() + Row(horizontalArrangement = Arrangement.spacedBy(OtherProfileCardSpacing)) { + ActionButton("프로젝트 전체 보기", modifier = Modifier.weight(1.35f)) + ActionButton("설정", modifier = Modifier.weight(1f)) + } } } } @@ -121,75 +101,43 @@ fun ProfileScreen( } } +@Composable +private fun Section(title: String, content: @Composable () -> Unit) { + Column(verticalArrangement = Arrangement.spacedBy(OtherProfileTitleContentSpacing)) { + ProfileSectionTitle(text = title) + content() + } +} + @Composable private fun ProfileHeader() { Row( modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(OtherProfileHeaderSpacing) ) { - Surface( - modifier = Modifier.size(92.dp), - shape = CircleShape, - color = Color(0xFFE3E3E3) - ) { + Surface(modifier = Modifier.size(92.dp), shape = CircleShape, color = Color(0xFFE3E3E3)) { Box(contentAlignment = Alignment.Center) { - Surface( - modifier = Modifier.size(38.dp), - shape = CircleShape, - color = Color(0xFF8F8F8F) - ) {} + Surface(modifier = Modifier.size(38.dp), shape = CircleShape, color = Color(0xFF8F8F8F)) {} } } - - Spacer(modifier = Modifier.size(20.dp)) - - Column { - Text( - text = "메타몽", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 35.sp, - lineHeight = 40.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Text( - text = "SW개발과 · 1학년", - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 23.sp, - lineHeight = 26.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Text( - text = "가입일 2025년 1월", - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 23.sp, - lineHeight = 26.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Column(verticalArrangement = Arrangement.spacedBy(OtherProfileHeaderTextSpacing)) { + Text("메타몽", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 35.sp, lineHeight = 40.sp) + Text("SW개발과 · 1학년", fontFamily = DotSans, fontSize = 23.sp, lineHeight = 26.sp) + Text("가입일 2025년 1월", fontFamily = DotSans, fontSize = 23.sp, lineHeight = 26.sp) } } } @Composable private fun ProfileSectionTitle(text: String) { - Text( - text = text, - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 27.sp, - lineHeight = 31.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Text(text, fontFamily = DotSans, fontSize = 27.sp, lineHeight = 31.sp) } @Composable -private fun EmptyProfileBox(height: androidx.compose.ui.unit.Dp) { +private fun EmptyProfileBox(height: Dp) { Surface( - modifier = Modifier - .fillMaxWidth() - .height(height), + modifier = Modifier.fillMaxWidth().height(height), shape = RoundedCornerShape(12.dp), color = Color.Transparent, border = BorderStroke(1.2.dp, ItdaGuideGray) @@ -198,70 +146,30 @@ private fun EmptyProfileBox(height: androidx.compose.ui.unit.Dp) { @Composable private fun ActivitySummaryRow() { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - ActivitySummaryCard( - value = "2", - label = "참여 프로젝트", - modifier = Modifier.weight(1f) - ) - ActivitySummaryCard( - value = "3", - label = "지원 내역", - modifier = Modifier.weight(1f) - ) - ActivitySummaryCard( - value = "1", - label = "받은 제안", - modifier = Modifier.weight(1f) - ) + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(OtherProfileCardSpacing)) { + ActivitySummaryCard("2", "참여 프로젝트", modifier = Modifier.weight(1f)) + ActivitySummaryCard("3", "지원 내역", modifier = Modifier.weight(1f)) + ActivitySummaryCard("1", "받은 제안", modifier = Modifier.weight(1f)) } } @Composable -private fun ActivitySummaryCard( - value: String, - label: String, - modifier: Modifier = Modifier -) { +private fun ActivitySummaryCard(value: String, label: String, modifier: Modifier = Modifier) { Surface( modifier = modifier.height(72.dp), shape = RoundedCornerShape(12.dp), color = Color.Transparent, border = BorderStroke(1.2.dp, ItdaGuideGray) ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = value, - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 17.sp, - lineHeight = 20.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Spacer(modifier = Modifier.height(3.dp)) - Text( - text = label, - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 11.sp, - lineHeight = 13.sp, - color = ItdaSecondaryTextColor - ) + Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center) { + Text(value, fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 17.sp) + Text(label, fontFamily = DotSans, fontSize = 11.sp, color = ItdaSecondaryTextColor) } } } @Composable -private fun ActionButton( - text: String, - modifier: Modifier = Modifier -) { +private fun ActionButton(text: String, modifier: Modifier = Modifier) { Surface( modifier = modifier.height(50.dp), shape = RoundedCornerShape(12.dp), @@ -269,14 +177,7 @@ private fun ActionButton( border = BorderStroke(1.2.dp, ItdaGuideGray) ) { Box(contentAlignment = Alignment.Center) { - Text( - text = text, - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 14.sp, - lineHeight = 16.sp, - color = ItdaSecondaryTextColor - ) + Text(text, fontFamily = DotSans, fontSize = 14.sp, color = ItdaSecondaryTextColor) } } } @@ -294,3 +195,4 @@ private fun ProfileScreenPreview() { ) } } + diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt index 6ab88c7..bd94cbf 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/ProjectStatusScreen.kt @@ -7,7 +7,6 @@ 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 @@ -39,6 +38,12 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme +private val StatusHorizontalPadding = 24.dp +private val StatusSectionSpacing = 14.dp +private val StatusChipSpacing = 8.dp +private val StatusListSpacing = 10.dp +private val StatusCardInnerSpacing = 6.dp + private enum class ProjectFilter(val label: String) { Participating("참여 중"), Applied("지원 내역"), @@ -63,14 +68,14 @@ fun ProjectStatusScreen( .fillMaxSize() .background(MaterialTheme.colorScheme.background) .statusBarsPadding() - .padding(horizontal = 24.dp) + .padding(horizontal = StatusHorizontalPadding), + verticalArrangement = Arrangement.spacedBy(StatusSectionSpacing) ) { ProjectStatusTopBar(onBackClick = onBackClick) - Spacer(modifier = Modifier.height(16.dp)) Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(StatusChipSpacing) ) { ProjectFilter.values().forEach { filter -> FilterChip( @@ -82,11 +87,9 @@ fun ProjectStatusScreen( } } - Spacer(modifier = Modifier.height(14.dp)) - LazyColumn( modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(10.dp) + verticalArrangement = Arrangement.spacedBy(StatusListSpacing) ) { items(statusItems(selectedFilter)) { item -> ProjectStatusCard(item = item) @@ -96,37 +99,20 @@ fun ProjectStatusScreen( } @Composable -private fun ProjectStatusTopBar( - onBackClick: () -> Unit -) { +private fun ProjectStatusTopBar(onBackClick: () -> Unit) { Row( - modifier = Modifier - .fillMaxWidth() - .height(72.dp), + modifier = Modifier.fillMaxWidth().height(72.dp), verticalAlignment = Alignment.CenterVertically ) { - Box( - modifier = Modifier - .size(36.dp) - .clickable(onClick = onBackClick), - contentAlignment = Alignment.Center - ) { - Text( - text = "<", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Box(modifier = Modifier.size(36.dp).clickable(onClick = onBackClick), contentAlignment = Alignment.Center) { + Text("<", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) } - Text( text = "프로젝트 현황", + modifier = Modifier.padding(start = 8.dp), fontFamily = DotSans, fontWeight = FontWeight.Bold, - fontSize = 23.sp, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.padding(start = 8.dp) + fontSize = 23.sp ) } } @@ -139,9 +125,7 @@ private fun FilterChip( modifier: Modifier = Modifier ) { Surface( - modifier = modifier - .height(38.dp) - .clickable(onClick = onClick), + modifier = modifier.height(38.dp).clickable(onClick = onClick), shape = RoundedCornerShape(22.dp), color = if (selected) ItdaHomeExploreButtonGray else ItdaWhite, border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) @@ -166,35 +150,19 @@ private fun ProjectStatusCard(item: ProjectStatusUiModel) { color = ItdaWhite, border = BorderStroke(1.dp, ItdaGuideGray.copy(alpha = 0.45f)) ) { - Column(modifier = Modifier.padding(horizontal = 14.dp, vertical = 14.dp)) { + Column( + modifier = Modifier.padding(horizontal = 14.dp, vertical = 14.dp), + verticalArrangement = Arrangement.spacedBy(StatusCardInnerSpacing) + ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( - text = item.title, - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Text( - text = item.status, - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 12.sp, - color = ItdaSecondaryTextColor - ) + Text(item.title, fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp) + Text(item.status, fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 12.sp, color = ItdaSecondaryTextColor) } - Spacer(modifier = Modifier.height(6.dp)) - Text( - text = item.description, - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 13.sp, - color = ItdaSecondaryTextColor - ) + Text(item.description, fontFamily = DotSans, fontSize = 13.sp, color = ItdaSecondaryTextColor) } } } @@ -205,12 +173,10 @@ private fun statusItems(filter: ProjectFilter): List { ProjectStatusUiModel("IT-DA Android", "프로필/설정 화면 구현 진행 중", "진행중"), ProjectStatusUiModel("캡스톤 매칭 서비스", "백엔드 API 연동 작업 진행", "진행중") ) - ProjectFilter.Applied -> listOf( ProjectStatusUiModel("AI 일정 도우미", "서류 심사 결과 대기 중", "대기"), ProjectStatusUiModel("스터디 팀빌딩", "인터뷰 일정 조율 중", "검토중") ) - ProjectFilter.Finished -> listOf( ProjectStatusUiModel("학교 축제 웹", "프론트엔드 구현 담당 완료", "완료"), ProjectStatusUiModel("동아리 홈페이지", "유지보수 배포까지 완료", "완료") @@ -221,8 +187,6 @@ private fun statusItems(filter: ProjectFilter): List { @Preview(showBackground = true) @Composable private fun ProjectStatusScreenPreview() { - ITDATheme { - ProjectStatusScreen(onBackClick = {}) - } + ITDATheme { ProjectStatusScreen(onBackClick = {}) } } diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt index 1313fc0..3f6996e 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/SelfIntroductionScreen.kt @@ -7,7 +7,6 @@ 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 @@ -39,6 +38,10 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme +private val IntroHorizontalPadding = 24.dp +private val IntroSectionSpacing = 10.dp +private val IntroTopSpacing = 20.dp + @Composable fun SelfIntroductionScreen( onBackClick: () -> Unit, @@ -53,28 +56,13 @@ fun SelfIntroductionScreen( if (showEditDialog) { AlertDialog( onDismissRequest = { showEditDialog = false }, - title = { - Text( - text = "자기소개 수정", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp - ) - }, + title = { Text("자기소개 수정", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) }, text = { OutlinedTextField( value = draftIntroduction, onValueChange = { draftIntroduction = it }, - modifier = Modifier - .fillMaxWidth() - .height(170.dp), - placeholder = { - Text( - text = "자기소개를 입력해 주세요.", - fontFamily = DotSans, - color = ItdaSecondaryTextColor - ) - }, + modifier = Modifier.fillMaxWidth().height(170.dp), + placeholder = { Text("자기소개를 입력해 주세요.", fontFamily = DotSans, color = ItdaSecondaryTextColor) }, shape = RoundedCornerShape(12.dp), colors = OutlinedTextFieldDefaults.colors( focusedBorderColor = ItdaGuideGray, @@ -100,7 +88,6 @@ fun SelfIntroductionScreen( text = "취소", modifier = Modifier.clickable { showEditDialog = false }, fontFamily = DotSans, - fontWeight = FontWeight.Normal, fontSize = 14.sp, color = ItdaSecondaryTextColor ) @@ -114,25 +101,17 @@ fun SelfIntroductionScreen( .fillMaxSize() .background(MaterialTheme.colorScheme.background) .statusBarsPadding() - .padding(horizontal = 24.dp) + .padding(horizontal = IntroHorizontalPadding), + verticalArrangement = Arrangement.spacedBy(IntroSectionSpacing) ) { SelfIntroductionTopBar(onBackClick = onBackClick) - Spacer(modifier = Modifier.height(20.dp)) - Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( - text = "자기소개", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 21.sp, - color = MaterialTheme.colorScheme.onBackground - ) - + Text("자기소개", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 21.sp) Surface( modifier = Modifier.clickable { draftIntroduction = introduction @@ -153,12 +132,8 @@ fun SelfIntroductionScreen( } } - Spacer(modifier = Modifier.height(10.dp)) - Surface( - modifier = Modifier - .fillMaxWidth() - .height(220.dp), + modifier = Modifier.fillMaxWidth().height(220.dp), shape = RoundedCornerShape(12.dp), color = ItdaWhite, border = BorderStroke(1.dp, ItdaGuideGray) @@ -167,10 +142,8 @@ fun SelfIntroductionScreen( text = introduction, modifier = Modifier.padding(14.dp), fontFamily = DotSans, - fontWeight = FontWeight.Normal, fontSize = 15.sp, - lineHeight = 22.sp, - color = MaterialTheme.colorScheme.onBackground + lineHeight = 22.sp ) } } @@ -179,34 +152,18 @@ fun SelfIntroductionScreen( @Composable private fun SelfIntroductionTopBar(onBackClick: () -> Unit) { Row( - modifier = Modifier - .fillMaxWidth() - .height(72.dp), - horizontalArrangement = Arrangement.Start, + modifier = Modifier.fillMaxWidth().height(72.dp), verticalAlignment = Alignment.CenterVertically ) { - Box( - modifier = Modifier - .size(36.dp) - .clickable(onClick = onBackClick), - contentAlignment = Alignment.Center - ) { - Text( - text = "<", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Box(modifier = Modifier.size(36.dp).clickable(onClick = onBackClick), contentAlignment = Alignment.Center) { + Text("<", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) } - Text( text = "자기소개 작성", + modifier = Modifier.padding(start = 8.dp), fontFamily = DotSans, fontWeight = FontWeight.Bold, - fontSize = 23.sp, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.padding(start = 8.dp) + fontSize = 23.sp ) } } @@ -214,8 +171,6 @@ private fun SelfIntroductionTopBar(onBackClick: () -> Unit) { @Preview(showBackground = true) @Composable private fun SelfIntroductionScreenPreview() { - ITDATheme { - SelfIntroductionScreen(onBackClick = {}) - } + ITDATheme { SelfIntroductionScreen(onBackClick = {}) } } diff --git a/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt index cf17edd..7f1b3f9 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/profile/VersionInfoScreen.kt @@ -7,7 +7,6 @@ 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 @@ -21,10 +20,10 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp 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.it_da.BuildConfig import com.example.it_da.ui.theme.DotSans import com.example.it_da.ui.theme.ItdaGuideGray @@ -32,6 +31,10 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor import com.example.it_da.ui.theme.ItdaWhite import com.example.it_da.ui.theme.ITDATheme +private val VersionHorizontalPadding = 24.dp +private val VersionSectionSpacing = 26.dp +private val VersionCardSpacing = 10.dp + @Composable fun VersionInfoScreen( onBackClick: () -> Unit, @@ -42,12 +45,10 @@ fun VersionInfoScreen( .fillMaxSize() .background(MaterialTheme.colorScheme.background) .statusBarsPadding() - .padding(horizontal = 24.dp) + .padding(horizontal = VersionHorizontalPadding), + verticalArrangement = Arrangement.spacedBy(VersionSectionSpacing) ) { VersionTopBar(onBackClick = onBackClick) - - Spacer(modifier = Modifier.height(26.dp)) - Surface( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), @@ -56,7 +57,7 @@ fun VersionInfoScreen( ) { Column( modifier = Modifier.padding(horizontal = 14.dp, vertical = 16.dp), - verticalArrangement = Arrangement.spacedBy(10.dp) + verticalArrangement = Arrangement.spacedBy(VersionCardSpacing) ) { VersionRow(label = "현재 버전", value = BuildConfig.VERSION_NAME) VersionRow(label = "버전 코드", value = BuildConfig.VERSION_CODE.toString()) @@ -66,73 +67,39 @@ fun VersionInfoScreen( } @Composable -private fun VersionTopBar( - onBackClick: () -> Unit -) { +private fun VersionTopBar(onBackClick: () -> Unit) { Row( - modifier = Modifier - .fillMaxWidth() - .height(72.dp), + modifier = Modifier.fillMaxWidth().height(72.dp), verticalAlignment = Alignment.CenterVertically ) { - Box( - modifier = Modifier - .size(36.dp) - .clickable(onClick = onBackClick), - contentAlignment = Alignment.Center - ) { - Text( - text = "<", - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onBackground - ) + Box(modifier = Modifier.size(36.dp).clickable(onClick = onBackClick), contentAlignment = Alignment.Center) { + Text("<", fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 20.sp) } - Text( text = "버전 정보", + modifier = Modifier.padding(start = 8.dp), fontFamily = DotSans, fontWeight = FontWeight.Bold, - fontSize = 23.sp, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.padding(start = 8.dp) + fontSize = 23.sp ) } } @Composable -private fun VersionRow( - label: String, - value: String -) { +private fun VersionRow(label: String, value: String) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text( - text = label, - fontFamily = DotSans, - fontWeight = FontWeight.Bold, - fontSize = 16.sp, - color = MaterialTheme.colorScheme.onBackground - ) - Text( - text = value, - fontFamily = DotSans, - fontWeight = FontWeight.Normal, - fontSize = 14.sp, - color = ItdaSecondaryTextColor - ) + Text(label, fontFamily = DotSans, fontWeight = FontWeight.Bold, fontSize = 16.sp) + Text(value, fontFamily = DotSans, fontSize = 14.sp, color = ItdaSecondaryTextColor) } } @Preview(showBackground = true) @Composable private fun VersionInfoScreenPreview() { - ITDATheme { - VersionInfoScreen(onBackClick = {}) - } + ITDATheme { VersionInfoScreen(onBackClick = {}) } }