diff --git a/app/src/main/java/com/example/it_da/data/repository/FakeHomeRepository.kt b/app/src/main/java/com/example/it_da/data/repository/FakeHomeRepository.kt index c2b4488..90332bb 100644 --- a/app/src/main/java/com/example/it_da/data/repository/FakeHomeRepository.kt +++ b/app/src/main/java/com/example/it_da/data/repository/FakeHomeRepository.kt @@ -12,8 +12,8 @@ class FakeHomeRepository : HomeRepository { override suspend fun getHomeDashboard(): Result { return Result.success( HomeDashboard( - userName = "000", - greetingDescription = "상상은 여기서 현실이 됩니다.\n당신의 프로젝트와 팀을 찾아보세요", + userName = "000님", + greetingDescription = "당신의 포트폴리오 첫 줄이 바뀝니다.\n당신과 딱 맞는 파트너를 찾아줘요", projectCount = HomeProjectCount( applyingCount = 3, participatingCount = 1, @@ -22,49 +22,49 @@ class FakeHomeRepository : HomeRepository { recommendedProjects = listOf( HomeRecommendedProject( id = "recommended-ai-planner", - title = "AI 기반 학습 플래너 [0부0부]", + title = "AI 기반 학습 플래너 [0수어부]", recruitingSummary = "백엔드 개발자 1명 모집", - statusText = "모집 중", + statusText = "모집중", techStacks = listOf("Back-end"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT과 2명, SW전공 1명 참여" ), HomeRecommendedProject( id = "recommended-hachiware", - title = "하지와레 키우기 [하키]", + title = "하치와레 키우기 [하키]", recruitingSummary = "프론트엔드 개발자 2명 모집", - statusText = "모집 중", + statusText = "모집중", techStacks = listOf("Back-end"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT과 2명, SW전공 1명 참여" ), HomeRecommendedProject( id = "recommended-pokemon", - title = "닮은 포켓몬 검사 [포켓몬백]", - recruitingSummary = "iOS 개발자ㆍ1명ㆍ디자이너 1명 모집", - statusText = "마감 임박", + title = "많은 포켓몬 검사 [포켓몬빵]", + recruitingSummary = "iOS 개발자 1명, 디자이너 1명 모집", + statusText = "마감임박", techStacks = listOf("iOS", "Design"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT과 2명, SW전공 3명 참여" ) ), participatingProjects = listOf( HomeParticipatingProject( id = "participating-dalbal", - title = "사랑을 이어주는 앱 [달발]", + title = "사람을 이어주는 앱 [달밤]", myRole = "내 역할 : iOS 개발", - statusText = "진행 중", - teamSummary = "팀원 4명ㆍ마감 2026-05-31" + statusText = "진행중", + teamSummary = "팀원 4명 · 마감 2026-05-31" ) ), notifications = listOf( HomeNotification( id = "notification-message", type = HomeNotificationType.MESSAGE, - message = "지원한 프로젝트에서 새 메시지가 있습니다", + message = "지방화 프로젝트에서 메시지가 도착했습니다", elapsedTime = "2분전" ), HomeNotification( id = "notification-join", type = HomeNotificationType.PROJECT_JOIN, - message = "백엔드 개발자 1명이 프로젝트에 합류 하였습니다", + message = "백엔드 개발자 1명이 프로젝트에 합류했습니다", elapsedTime = "2분전" ) ) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeNotificationSection.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeNotificationSection.kt index c5859bc..7e61912 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeNotificationSection.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeNotificationSection.kt @@ -22,7 +22,7 @@ fun HomeNotificationSection( ) { Column(modifier = modifier.fillMaxWidth()) { ItdaSectionHeader( - title = "알림 요약ㆍ확인", + title = "알림 모아 · 확인", titleFontWeight = FontWeight.Medium ) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeProfileSummarySection.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeProfileSummarySection.kt index 774d7fd..86d3195 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeProfileSummarySection.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/HomeProfileSummarySection.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.res.painterResource 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.screen.home.state.HomeProjectCountUiModel +import com.example.it_da.domain.model.HomeProjectCount import com.example.it_da.ui.theme.DotSans import com.example.it_da.ui.theme.ItdaHomeCardBorderGray import com.example.it_da.ui.theme.ItdaPrimaryTextColor @@ -35,7 +35,7 @@ fun HomeProfileSummarySection( @DrawableRes profileImageResId: Int, userName: String, greetingDescription: String, - projectCount: HomeProjectCountUiModel, + projectCount: HomeProjectCount, modifier: Modifier = Modifier ) { Column(modifier = modifier.fillMaxWidth()) { @@ -53,7 +53,7 @@ fun HomeProfileSummarySection( Column { Text( - text = "안녕하세요, ${userName}님 👋", + text = "안녕하세요, $userName", color = ItdaPrimaryTextColor, fontFamily = DotSans, fontWeight = FontWeight.Bold, @@ -83,7 +83,7 @@ fun HomeProfileSummarySection( // Displays the three count values that summarize the user's project activity. @Composable private fun HomeProjectCountCard( - projectCount: HomeProjectCountUiModel, + projectCount: HomeProjectCount, modifier: Modifier = Modifier ) { Surface( diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectCard.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectCard.kt index c8f4d32..dadf559 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectCard.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectCard.kt @@ -19,7 +19,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.example.it_da.ui.screen.home.state.ParticipatingProjectUiModel +import com.example.it_da.domain.model.HomeParticipatingProject +import com.example.it_da.ui.screen.home.state.detailText import com.example.it_da.ui.theme.DotSans import com.example.it_da.ui.theme.ItdaPrimaryTextColor import com.example.it_da.ui.theme.ItdaSecondaryTextColor @@ -27,7 +28,7 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor // Displays one participating project with role and progress text supplied by state. @Composable fun ParticipatingProjectCard( - project: ParticipatingProjectUiModel, + project: HomeParticipatingProject, onProjectClick: (String) -> Unit, onDetailClick: (String) -> Unit, modifier: Modifier = Modifier diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectSection.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectSection.kt index 69f4e2e..301dbe0 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectSection.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/ParticipatingProjectSection.kt @@ -8,13 +8,13 @@ import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.example.it_da.domain.model.HomeParticipatingProject import com.example.it_da.ui.component.ItdaSectionHeader -import com.example.it_da.ui.screen.home.state.ParticipatingProjectUiModel // Shows the user's participating projects with a card type separate from recommendations. @Composable fun ParticipatingProjectSection( - projects: List, + projects: List, onProjectClick: (String) -> Unit, onDetailClick: (String) -> Unit, modifier: Modifier = Modifier diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectCard.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectCard.kt index a8e05a0..ea63e94 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectCard.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectCard.kt @@ -23,7 +23,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.example.it_da.ui.screen.home.state.RecommendedProjectUiModel +import com.example.it_da.domain.model.HomeRecommendedProject +import com.example.it_da.ui.screen.home.state.detailText import com.example.it_da.ui.theme.DotSans import com.example.it_da.ui.theme.ItdaPrimaryTextColor import com.example.it_da.ui.theme.ItdaSecondaryTextColor @@ -31,7 +32,7 @@ import com.example.it_da.ui.theme.ItdaSecondaryTextColor // Displays one recommended project with state-provided title, status, stack, and participant text. @Composable fun RecommendedProjectCard( - project: RecommendedProjectUiModel, + project: HomeRecommendedProject, onProjectClick: (String) -> Unit, onDetailClick: (String) -> Unit, modifier: Modifier = Modifier diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectSection.kt b/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectSection.kt index 54a2f7a..4785da0 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectSection.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/component/RecommendedProjectSection.kt @@ -9,13 +9,13 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.example.it_da.domain.model.HomeRecommendedProject import com.example.it_da.ui.component.ItdaSectionHeader -import com.example.it_da.ui.screen.home.state.RecommendedProjectUiModel // Shows the recommended project section with independently clickable project cards. @Composable fun RecommendedProjectSection( - projects: List, + projects: List, onProjectClick: (String) -> Unit, onDetailClick: (String) -> Unit, modifier: Modifier = Modifier diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/mapper/HomeUiStateMapper.kt b/app/src/main/java/com/example/it_da/ui/screen/home/mapper/HomeUiStateMapper.kt index 846f520..fcca1e7 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/mapper/HomeUiStateMapper.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/mapper/HomeUiStateMapper.kt @@ -4,14 +4,8 @@ import com.example.it_da.R import com.example.it_da.domain.model.HomeDashboard import com.example.it_da.domain.model.HomeNotification import com.example.it_da.domain.model.HomeNotificationType -import com.example.it_da.domain.model.HomeParticipatingProject -import com.example.it_da.domain.model.HomeProjectCount -import com.example.it_da.domain.model.HomeRecommendedProject 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 // Converts domain home dashboard data into UI state for the Home screen. fun HomeDashboard.toHomeUiState(): HomeUiState { @@ -19,51 +13,15 @@ fun HomeDashboard.toHomeUiState(): HomeUiState { userName = userName, profileImageResId = R.drawable.home_profile_placeholder, greetingDescription = greetingDescription, - projectCount = projectCount.toHomeProjectCountUiModel(), - recommendedProjects = recommendedProjects.map { project -> - project.toRecommendedProjectUiModel() - }, - participatingProjects = participatingProjects.map { project -> - project.toParticipatingProjectUiModel() - }, + projectCount = projectCount, + recommendedProjects = recommendedProjects, + participatingProjects = participatingProjects, notifications = notifications.map { notification -> notification.toHomeNotificationUiModel() } ) } -// Converts domain project count data into the count model used by the Home header. -private fun HomeProjectCount.toHomeProjectCountUiModel(): HomeProjectCountUiModel { - return HomeProjectCountUiModel( - applyingCount = applyingCount, - participatingCount = participatingCount, - completedCount = completedCount - ) -} - -// Converts a domain recommended project into the card model used by the Home UI. -private fun HomeRecommendedProject.toRecommendedProjectUiModel(): RecommendedProjectUiModel { - return RecommendedProjectUiModel( - id = id, - title = title, - recruitingSummary = recruitingSummary, - statusText = statusText, - techStacks = techStacks, - participantSummary = participantSummary - ) -} - -// Converts a domain participating project into the card model used by the Home UI. -private fun HomeParticipatingProject.toParticipatingProjectUiModel(): ParticipatingProjectUiModel { - return ParticipatingProjectUiModel( - id = id, - title = title, - myRole = myRole, - statusText = statusText, - teamSummary = teamSummary - ) -} - // Converts a domain notification into the image-backed model used by the Home UI. private fun HomeNotification.toHomeNotificationUiModel(): HomeNotificationUiModel { return HomeNotificationUiModel( diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/screen/HomeScreen.kt b/app/src/main/java/com/example/it_da/ui/screen/home/screen/HomeScreen.kt index daf6b69..2a5e319 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/screen/HomeScreen.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/screen/HomeScreen.kt @@ -19,20 +19,20 @@ 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.domain.model.HomeParticipatingProject +import com.example.it_da.domain.model.HomeProjectCount +import com.example.it_da.domain.model.HomeRecommendedProject import com.example.it_da.ui.screen.home.component.HomeBottomNavigationBar import com.example.it_da.ui.screen.home.component.HomeNotificationSection import com.example.it_da.ui.screen.home.component.HomeProfileSummarySection import com.example.it_da.ui.screen.home.component.ParticipatingProjectSection import com.example.it_da.ui.screen.home.component.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.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 @@ -148,6 +148,8 @@ private fun HomeContent( text = "프로젝트 탐색하기", containerColor = ItdaHomeExploreButtonGray ) + + Spacer(modifier = Modifier.height(16.dp)) } } @@ -176,39 +178,47 @@ 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 = "000님", profileImageResId = R.drawable.home_profile_placeholder, - greetingDescription = "상상은 여기서 현실이 됩니다.\n당신의 프로젝트와 팀을 찾아보세요", - projectCount = HomeProjectCountUiModel( + greetingDescription = "당신의 포트폴리오 첫 줄이 바뀝니다.\n당신과 딱 맞는 파트너를 찾아줘요", + projectCount = HomeProjectCount( applyingCount = 3, participatingCount = 1, completedCount = 1 ), recommendedProjects = listOf( - RecommendedProjectUiModel( + HomeRecommendedProject( id = "recommended-ai-planner", - title = "AI 기반 학습 플래너 [0부0부]", + title = "AI 기반 학습 플래너 [0수어부]", recruitingSummary = "백엔드 개발자 1명 모집", - statusText = "모집 중", + statusText = "모집중", + techStacks = listOf("Back-end"), + participantSummary = "IoT과 2명, SW전공 1명 참여" + ), + HomeRecommendedProject( + id = "recommended-hachiware", + title = "하치와레 키우기 [하키]", + recruitingSummary = "프론트엔드 개발자 2명 모집", + statusText = "모집중", techStacks = listOf("Back-end"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT과 2명, SW전공 1명 참여" ), - RecommendedProjectUiModel( + HomeRecommendedProject( id = "recommended-pokemon", - title = "닮은 포켓몬 검사 [포켓몬백]", - recruitingSummary = "iOS 개발자ㆍ1명ㆍ디자이너 1명 모집", - statusText = "마감 임박", + title = "많은 포켓몬 검사 [포켓몬빵]", + recruitingSummary = "iOS 개발자 1명, 디자이너 1명 모집", + statusText = "마감임박", techStacks = listOf("iOS", "Design"), - participantSummary = "IoT과ㆍ2명, SW과 1명 참여" + participantSummary = "IoT과 2명, SW전공 3명 참여" ) ), participatingProjects = listOf( - ParticipatingProjectUiModel( + HomeParticipatingProject( id = "participating-dalbal", - title = "사랑을 이어주는 앱 [달발]", + title = "사람을 이어주는 앱 [달밤]", myRole = "내 역할 : iOS 개발", - statusText = "진행 중", - teamSummary = "팀원 4명ㆍ마감 2026-05-31" + statusText = "진행중", + teamSummary = "팀원 4명 · 마감 2026-05-31" ) ), notifications = listOf( @@ -216,7 +226,14 @@ private fun previewHomeUiState(): HomeUiState { id = "notification-message", imageResId = R.drawable.home_notification_mailbox, imageDescription = "새 메시지 알림", - message = "지원한 프로젝트에서 새 메시지가 있습니다", + message = "지방화 프로젝트에서 메시지가 도착했습니다", + elapsedTime = "2분전" + ), + HomeNotificationUiModel( + id = "notification-join", + imageResId = R.drawable.home_notification_laptop, + imageDescription = "프로젝트 참여 알림", + message = "백엔드 개발자 1명이 프로젝트에 합류했습니다", elapsedTime = "2분전" ) ) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeProjectCountUiModel.kt b/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeProjectCountUiModel.kt deleted file mode 100644 index 60d90c9..0000000 --- a/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeProjectCountUiModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.it_da.ui.screen.home.state - -// Represents the project count summary shown at the top of the home screen. -data class HomeProjectCountUiModel( - val applyingCount: Int, - val participatingCount: Int, - val completedCount: Int -) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeProjectUiText.kt b/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeProjectUiText.kt new file mode 100644 index 0000000..608bfe4 --- /dev/null +++ b/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeProjectUiText.kt @@ -0,0 +1,14 @@ +package com.example.it_da.ui.screen.home.state + +import com.example.it_da.domain.model.HomeParticipatingProject +import com.example.it_da.domain.model.HomeRecommendedProject + +private const val HOME_PROJECT_DETAIL_TEXT = "자세히 보기" + +// Provides shared UI-only text for project cards without duplicating the data model. +val HomeRecommendedProject.detailText: String + get() = HOME_PROJECT_DETAIL_TEXT + +// Provides shared UI-only text for project cards without duplicating the data model. +val HomeParticipatingProject.detailText: String + get() = HOME_PROJECT_DETAIL_TEXT diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeUiState.kt b/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeUiState.kt index 7da8c6d..017f0a4 100644 --- a/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeUiState.kt +++ b/app/src/main/java/com/example/it_da/ui/screen/home/state/HomeUiState.kt @@ -2,18 +2,21 @@ package com.example.it_da.ui.screen.home.state import androidx.annotation.DrawableRes import com.example.it_da.R +import com.example.it_da.domain.model.HomeParticipatingProject +import com.example.it_da.domain.model.HomeProjectCount +import com.example.it_da.domain.model.HomeRecommendedProject // Holds every dynamic value that the home screen needs to display. data class HomeUiState( val userName: String = "", @DrawableRes val profileImageResId: Int = R.drawable.home_profile_placeholder, val greetingDescription: String = "", - val projectCount: HomeProjectCountUiModel = HomeProjectCountUiModel( + val projectCount: HomeProjectCount = HomeProjectCount( applyingCount = 0, participatingCount = 0, completedCount = 0 ), - val recommendedProjects: List = emptyList(), - val participatingProjects: List = emptyList(), + val recommendedProjects: List = emptyList(), + val participatingProjects: List = emptyList(), val notifications: List = emptyList() ) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/state/ParticipatingProjectUiModel.kt b/app/src/main/java/com/example/it_da/ui/screen/home/state/ParticipatingProjectUiModel.kt deleted file mode 100644 index 4828fdc..0000000 --- a/app/src/main/java/com/example/it_da/ui/screen/home/state/ParticipatingProjectUiModel.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.example.it_da.ui.screen.home.state - -// Represents a project the user is already participating in. -data class ParticipatingProjectUiModel( - val id: String, - val title: String, - val myRole: String, - val statusText: String, - val teamSummary: String, - val detailText: String = "자세히 보기" -) diff --git a/app/src/main/java/com/example/it_da/ui/screen/home/state/RecommendedProjectUiModel.kt b/app/src/main/java/com/example/it_da/ui/screen/home/state/RecommendedProjectUiModel.kt deleted file mode 100644 index 68ca42e..0000000 --- a/app/src/main/java/com/example/it_da/ui/screen/home/state/RecommendedProjectUiModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.it_da.ui.screen.home.state - -// Represents a recommended project card whose visible text can come from remote data later. -data class RecommendedProjectUiModel( - val id: String, - val title: String, - val recruitingSummary: String, - val statusText: String, - val techStacks: List, - val participantSummary: String, - val detailText: String = "자세히 보기" -) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1f4a166..72a7c6f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "9.2.0" +agp = "9.1.0" coreKtx = "1.10.1" junit = "4.13.2" junitVersion = "1.1.5"