diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml
index 5d41895..63165ba 100644
--- a/.idea/caches/deviceStreaming.xml
+++ b/.idea/caches/deviceStreaming.xml
@@ -330,6 +330,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -821,6 +833,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/hsLink/hslink/core/DummyComponent.kt b/app/src/main/java/com/hsLink/hslink/core/DummyComponent.kt
deleted file mode 100644
index aa23361..0000000
--- a/app/src/main/java/com/hsLink/hslink/core/DummyComponent.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.hsLink.hslink.core
-
-class DummyComponent {
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/core/designsystem/.gitkeep b/app/src/main/java/com/hsLink/hslink/core/designsystem/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt b/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt
new file mode 100644
index 0000000..25daaef
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt
@@ -0,0 +1,110 @@
+package com.hsLink.hslink.core.designsystem.component
+
+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.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.Dialog
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
+
+@Composable
+fun HsLinkDialog(
+ title: String,
+ message: String,
+ confirmText: String,
+ dismissText: String,
+ onConfirm: () -> Unit,
+ onDismiss: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Dialog(onDismissRequest = onDismiss) {
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .background(
+ color = HsLinkTheme.colors.Common,
+ shape = RoundedCornerShape(12.dp)
+ )
+ .padding(24.dp),
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ Text(
+ text = title,
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_20Strong
+ )
+
+ Text(
+ text = message,
+ color = HsLinkTheme.colors.Grey500,
+ style = HsLinkTheme.typography.body_14Normal
+ )
+
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center
+ ) {
+ Box(
+ modifier = Modifier
+ .background(
+ color = HsLinkTheme.colors.Grey100,
+ shape = RoundedCornerShape(8.dp)
+ )
+ .noRippleClickable(onClick = onDismiss)
+ .padding(vertical = 12.dp, horizontal = 40.dp)
+ ) {
+ Text(
+ text = dismissText,
+ color = HsLinkTheme.colors.Grey500,
+ style = HsLinkTheme.typography.btm_M,
+ )
+ }
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ Box(
+ modifier = Modifier
+ .background(
+ color = HsLinkTheme.colors.DeepBlue500,
+ shape = RoundedCornerShape(8.dp)
+ )
+ .noRippleClickable(onClick = onConfirm)
+ .padding(vertical = 12.dp, horizontal = 40.dp)
+ ) {
+ Text(
+ text = confirmText,
+ color = HsLinkTheme.colors.Common,
+ style = HsLinkTheme.typography.btm_M,
+ )
+ }
+ }
+ }
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun HsLinkDialogPreview() {
+ HsLinkTheme {
+ HsLinkDialog(
+ title = "글쓰기를 종료하시겠습니까?",
+ message = "작성 중인 내용이 저장되지 않습니다.",
+ confirmText = "나가기",
+ dismissText = "취소하기",
+ onConfirm = {},
+ onDismiss = {}
+ )
+ }
+}
diff --git a/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt b/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt
index 6167737..77d3221 100644
--- a/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt
+++ b/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt
@@ -93,11 +93,13 @@ fun HsLinkTextField(
)
}
}
- Icon(
- imageVector = ImageVector.vectorResource(id = leadingIconRes ?: 0),
- contentDescription = null,
- tint = Color.Unspecified
- )
+ leadingIconRes?.let { iconRes ->
+ Icon(
+ imageVector = ImageVector.vectorResource(id = iconRes),
+ contentDescription = null,
+ tint = Color.Unspecified
+ )
+ }
}
}
)
diff --git a/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt b/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt
index 0ac5600..c89e4c4 100644
--- a/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt
+++ b/app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt
@@ -17,6 +17,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.hsLink.hslink.R
import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
@Composable
fun HsLinkTopBar(
@@ -25,6 +26,9 @@ fun HsLinkTopBar(
@DrawableRes rightIconFirst: Int? = null,
@DrawableRes rightIconSecond: Int? = null,
@DrawableRes leftIcon: Int? = null,
+ onRightIconFirstClick: () -> Unit = {},
+ onRightIconSecondClick: () -> Unit = {},
+ onLeftIconClick: () -> Unit = {}
) {
Row(
modifier = modifier
@@ -36,7 +40,8 @@ fun HsLinkTopBar(
leftIcon?.let {
Icon(
imageVector = ImageVector.vectorResource(id = it),
- contentDescription = "leftIcon"
+ contentDescription = "leftIcon",
+ modifier = Modifier.noRippleClickable(onClick = onLeftIconClick)
)
}
@@ -47,14 +52,16 @@ fun HsLinkTopBar(
rightIconFirst?.let {
Icon(
imageVector = ImageVector.vectorResource(id = it),
- contentDescription = "rightIconFirst"
+ contentDescription = "rightIconFirst",
+ modifier = Modifier.noRippleClickable(onClick = onRightIconFirstClick)
)
}
rightIconSecond?.let {
Icon(
imageVector = ImageVector.vectorResource(id = it),
- contentDescription = "rightIconSecond"
+ contentDescription = "rightIconSecond",
+ modifier = Modifier.noRippleClickable(onClick = onRightIconSecondClick)
)
}
}
diff --git a/app/src/main/java/com/hsLink/hslink/data/local/PostDetail.kt b/app/src/main/java/com/hsLink/hslink/data/local/PostDetail.kt
new file mode 100644
index 0000000..d026efa
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/data/local/PostDetail.kt
@@ -0,0 +1,21 @@
+package com.hsLink.hslink.data.local
+
+data class PostDetail(
+ val id: String,
+ val authorName: String,
+ val authorMajor: String,
+ val boardType: String,
+ val timeAgo: String,
+ val title: String,
+ val content: String,
+ val isMyPost: Boolean,
+ val comments: List
+)
+
+data class Comment(
+ val id: String,
+ val authorName: String,
+ val timeAgo: String,
+ val content: String,
+ val isMyComment: Boolean
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/CommunityScreen.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/CommunityScreen.kt
deleted file mode 100644
index f2b8d20..0000000
--- a/app/src/main/java/com/hsLink/hslink/presentation/community/CommunityScreen.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.hsLink.hslink.presentation.community
-
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-
-
-@Composable
-fun CommunityRoute(
- paddingValues: PaddingValues,
-) {
- CommunityScreen(paddingValues)
-}
-
-@Composable
-fun CommunityScreen(
- paddingValues: PaddingValues,
- modifier: Modifier = Modifier,
-) {
- Text(
- text = "Community Screen",
- modifier = modifier
- .padding(paddingValues)
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt
new file mode 100644
index 0000000..454eef9
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt
@@ -0,0 +1,93 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Icon
+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.graphics.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
+
+@Composable
+fun CommentItem(
+ authorName: String,
+ timeAgo: String,
+ content: String,
+ isMyComment: Boolean,
+ onDeleteClick: () -> Unit,
+ modifier: Modifier = Modifier
+) {
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 12.dp),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.Top
+ ) {
+ Column(
+ modifier = Modifier.weight(1f),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ text = authorName,
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_14Strong
+ )
+
+ Text(
+ text = timeAgo,
+ color = HsLinkTheme.colors.Grey400,
+ style = HsLinkTheme.typography.caption_12Normal
+ )
+ }
+
+ Text(
+ text = content,
+ color = HsLinkTheme.colors.Grey600,
+ style = HsLinkTheme.typography.body_14Normal
+ )
+ }
+
+ if (isMyComment) {
+ Icon(
+ imageVector = ImageVector.vectorResource(id = R.drawable.ic_community_kebab),
+ contentDescription = "댓글 삭제",
+ tint = Color.Unspecified,
+ modifier = Modifier
+ .size(24.dp)
+ .noRippleClickable(onClick = onDeleteClick)
+ )
+ }
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun CommentItemPreview() {
+ HsLinkTheme {
+ CommentItem(
+ authorName = "송효재",
+ timeAgo = "21학번",
+ content = "자소서 어떻게 작성하셨나요? 주로 보는 인재상이 있는지 궁금합니다.",
+ isMyComment = true,
+ onDeleteClick = {}
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt
new file mode 100644
index 0000000..49693d1
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt
@@ -0,0 +1,87 @@
+package com.hsLink.hslink.presentation.home.component
+
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Icon
+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.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewCommunityCardItem() {
+ HsLinkTheme {
+ CommunityCardItem(
+ userName = "John Doe",
+ userMajor = "Computer Science",
+ userInfo = "Senior at XYZ University",
+ onClick = {},
+ )
+ }
+}
+
+@Composable
+fun CommunityCardItem(
+ userName: String,
+ userMajor: String,
+ userInfo: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .border(
+ width = 1.dp,
+ color = HsLinkTheme.colors.Grey100,
+ shape = RoundedCornerShape(8.dp)
+ )
+ .noRippleClickable(onClick = onClick)
+ .padding(16.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Column(
+ modifier = Modifier.weight(1f),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Text(
+ text = userName,
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_16Strong,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+
+ Text(
+ text = userMajor,
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.body_14Normal,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+
+ Text(
+ text = userInfo,
+ color = HsLinkTheme.colors.Grey400,
+ style = HsLinkTheme.typography.caption_12Normal,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt
new file mode 100644
index 0000000..25d915a
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt
@@ -0,0 +1,80 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Tab
+import androidx.compose.material3.TabRow
+import androidx.compose.material3.TabRowDefaults
+import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewCommunityTabLayout() {
+ HsLinkTheme {
+ CommunityTabLayout(
+ selectedTab = CommunityTab.Popular,
+ onTabSelected = {}
+ )
+ }
+}
+
+enum class CommunityTab(val title: String) {
+ Popular("인기글"),
+ Free("자유게시판"),
+ Promotion("홍보게시판"),
+ Notice("공지")
+}
+
+@Composable
+fun CommunityTabLayout(
+ selectedTab: CommunityTab,
+ onTabSelected: (CommunityTab) -> Unit,
+ modifier: Modifier = Modifier
+) {
+ val tabs = CommunityTab.entries
+
+ HorizontalDivider(
+ thickness = 1.dp,
+ color = HsLinkTheme.colors.Grey100,
+ )
+ TabRow(
+ selectedTabIndex = tabs.indexOf(selectedTab),
+ modifier = modifier.fillMaxWidth(),
+ contentColor = HsLinkTheme.colors.SkyBlue500,
+ containerColor = HsLinkTheme.colors.Common,
+ divider = {},
+ indicator = { tabPositions ->
+ TabRowDefaults.SecondaryIndicator(
+ modifier = Modifier.tabIndicatorOffset(tabPositions[tabs.indexOf(selectedTab)]),
+ color = HsLinkTheme.colors.SkyBlue500,
+ height = 2.dp
+ )
+ }
+ ) {
+ tabs.forEach { tab ->
+ Tab(
+ selected = selectedTab == tab,
+ onClick = { onTabSelected(tab) },
+ modifier = Modifier.padding(vertical = 12.dp)
+ ) {
+ Text(
+ text = tab.title,
+ style = HsLinkTheme.typography.title_16Strong,
+ color = if (selectedTab == tab) {
+ HsLinkTheme.colors.SkyBlue500
+ } else {
+ HsLinkTheme.colors.Grey200
+ }
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt
new file mode 100644
index 0000000..319273b
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt
@@ -0,0 +1,91 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.material3.Icon
+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.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
+
+@Composable
+fun CommentInput(
+ value: String,
+ onValueChange: (String) -> Unit,
+ onSendClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .background(HsLinkTheme.colors.Grey100)
+ .padding(horizontal = 16.dp, vertical = 12.dp)
+ .border(
+ width = 1.dp,
+ color = HsLinkTheme.colors.Grey200,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .padding(horizontal = 16.dp, vertical = 10.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ BasicTextField(
+ value = value,
+ onValueChange = onValueChange,
+ modifier = Modifier
+ .weight(1f)
+ .background(color = HsLinkTheme.colors.Grey100),
+ textStyle = HsLinkTheme.typography.body_14Normal.copy(
+ color = HsLinkTheme.colors.Grey700
+ ),
+ decorationBox = { innerTextField ->
+ if (value.isEmpty()) {
+ Text(
+ text = "댓글을 입력해주세요",
+ color = HsLinkTheme.colors.Grey400,
+ style = HsLinkTheme.typography.body_14Normal
+ )
+ }
+ innerTextField()
+ }
+ )
+
+ Icon(
+ imageVector = ImageVector.vectorResource(id = R.drawable.ic_community_post_send),
+ contentDescription = "댓글 전송",
+ tint = if (value.isNotBlank()) {
+ HsLinkTheme.colors.DeepBlue500
+ } else {
+ HsLinkTheme.colors.Grey300
+ },
+ modifier = Modifier
+ .noRippleClickable(
+ enabled = value.isNotBlank(),
+ onClick = onSendClick
+ )
+ )
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun CommentInputPreview() {
+ HsLinkTheme {
+ CommentInput(
+ value = "",
+ onValueChange = {},
+ onSendClick = {}
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt
new file mode 100644
index 0000000..8044b65
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt
@@ -0,0 +1,46 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+
+@Composable
+fun EmptyComment(
+ modifier: Modifier = Modifier
+) {
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(vertical = 60.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ Text(
+ text = "아직 댓글이 없어요",
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_16Strong
+ )
+
+ Text(
+ text = "말을 걸어 대화를 시작하세요.",
+ color = HsLinkTheme.colors.Grey500,
+ style = HsLinkTheme.typography.body_14Normal
+ )
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun EmptyCommentPreview() {
+ HsLinkTheme {
+ EmptyComment()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt
new file mode 100644
index 0000000..8548bea
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt
@@ -0,0 +1,48 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+
+@Composable
+fun PostContent(
+ title: String,
+ content: String,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 16.dp)
+ ) {
+ Text(
+ text = title,
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_16Strong
+ )
+
+ Text(
+ text = content,
+ color = HsLinkTheme.colors.Grey600,
+ style = HsLinkTheme.typography.body_14Normal,
+ modifier = Modifier.padding(top = 12.dp)
+ )
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun PostContentPreview() {
+ HsLinkTheme {
+ PostContent(
+ title = "추천 채용 한성 IT 추천 채용 공고 - 네이버 영업직 구합니다.",
+ content = "제가 다니고 있는 한성 it에서 추천 채용이 올라와 공유드립니다. 이미지 첨고해주세요"
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt
new file mode 100644
index 0000000..ad8c9bf
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt
@@ -0,0 +1,65 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+
+@Composable
+fun PostHeader(
+ authorName: String,
+ authorMajor: String,
+ boardType: String,
+ timeAgo: String,
+ modifier: Modifier = Modifier
+) {
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 12.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Text(
+ text = "$authorName",
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.caption_12Normal
+ )
+
+ Text(
+ text = boardType,
+ color = HsLinkTheme.colors.SkyBlue500,
+ style = HsLinkTheme.typography.caption_12Normal
+ )
+ }
+
+ Text(
+ text = "$timeAgo · $authorMajor",
+ color = HsLinkTheme.colors.Grey400,
+ style = HsLinkTheme.typography.caption_12Normal
+ )
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun PostHeaderPreview() {
+ HsLinkTheme {
+ PostHeader(
+ authorName = "송효재",
+ authorMajor = "재직중",
+ boardType = "(작성자)",
+ timeAgo = "21학번"
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt
new file mode 100644
index 0000000..2990dc8
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt
@@ -0,0 +1,105 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.component.HsLinkTextField
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+
+enum class BoardType(val displayName: String) {
+ FREE("자유게시판"),
+ PROMOTION("홍보게시판"),
+ NOTICE("공지게시판")
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun BoardSelectionFieldPreview() {
+ HsLinkTheme {
+ BoardSelectionField(
+ selectedBoard = "자유게시판",
+ isExpanded = false,
+ onExpandedChange = {},
+ onBoardSelected = {},
+ isFocused = false,
+ onFocusChanged = {},
+ )
+ }
+}
+
+@Composable
+fun BoardSelectionField(
+ selectedBoard: String,
+ isExpanded: Boolean,
+ onExpandedChange: (Boolean) -> Unit,
+ onBoardSelected: (BoardType) -> Unit,
+ isFocused: Boolean,
+ onFocusChanged: (Boolean) -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Box(modifier = modifier) {
+ HsLinkTextField(
+ value = selectedBoard,
+ placeholder = "게시판을 선택해주세요",
+ onValueChanged = { },
+ borderColor = if (isFocused || isExpanded) {
+ HsLinkTheme.colors.DeepBlue500
+ } else {
+ HsLinkTheme.colors.Grey200
+ },
+ backgroundColor = HsLinkTheme.colors.Common,
+ onFocusChanged = onFocusChanged,
+ leadingIconRes = if(!isExpanded) R.drawable.ic_community_arrow_down else R.drawable.ic_community_arrow_up,
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Box(
+ modifier = Modifier
+ .matchParentSize()
+ .padding(horizontal = 16.dp)
+ .clickable(
+ interactionSource = remember { MutableInteractionSource() },
+ indication = null
+ ) {
+ onExpandedChange(!isExpanded)
+ }
+ )
+
+ DropdownMenu(
+ expanded = isExpanded,
+ onDismissRequest = { onExpandedChange(false) },
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(HsLinkTheme.colors.Common)
+ ) {
+ BoardType.entries.forEach { board ->
+ DropdownMenuItem(
+ text = {
+ Text(
+ text = board.displayName,
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.body_14Normal
+ )
+ },
+ onClick = {
+ onBoardSelected(board)
+ onExpandedChange(false)
+ },
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt
new file mode 100644
index 0000000..fbcb8f6
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt
@@ -0,0 +1,70 @@
+package com.hsLink.hslink.presentation.community.component
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Icon
+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.graphics.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewCommunityWriteButton() {
+ HsLinkTheme {
+ CommunityWriteButton(
+ isDone = true,
+ onClick = {}
+ )
+ }
+}
+
+@Composable
+fun CommunityWriteButton(
+ isDone: Boolean,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ val backColor = when (isDone) {
+ true -> HsLinkTheme.colors.DeepBlue500
+ false -> HsLinkTheme.colors.Grey200
+ }
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .background(backColor, shape = RoundedCornerShape(8.dp))
+ .noRippleClickable(onClick = onClick)
+ .padding(vertical = 12.dp),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Icon(
+ imageVector = ImageVector.vectorResource(R.drawable.ic_community_button),
+ contentDescription = null,
+ tint = Color.Unspecified
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ Text(
+ text = "글작성 마치기",
+ color = HsLinkTheme.colors.Common,
+ style = HsLinkTheme.typography.btm_L
+ )
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt
similarity index 57%
rename from app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt
rename to app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt
index 0916c17..bdcbe0f 100644
--- a/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt
@@ -1,4 +1,4 @@
-package com.hsLink.hslink.presentation.home.navigation
+package com.hsLink.hslink.presentation.community.navigation.main
import androidx.compose.foundation.layout.PaddingValues
import androidx.navigation.NavController
@@ -6,7 +6,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.hsLink.hslink.core.navigation.MainTabRoute
-import com.hsLink.hslink.presentation.community.CommunityRoute
+import com.hsLink.hslink.presentation.community.screen.main.CommunityRoute
import kotlinx.serialization.Serializable
fun NavController.navigateToCommunity(navOptions: NavOptions? = null) {
@@ -15,9 +15,17 @@ fun NavController.navigateToCommunity(navOptions: NavOptions? = null) {
fun NavGraphBuilder.communityNavGraph(
padding: PaddingValues,
+ navigateUp : () -> Unit,
+ navigateToWriting : () -> Unit,
+ navigateToPost: (String) -> Unit,
) {
composable {
- CommunityRoute(padding)
+ CommunityRoute(
+ padding,
+ navigateUp = navigateUp,
+ navigateWriteCommunity = navigateToWriting,
+ navigateToPost = navigateToPost
+ )
}
}
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt
new file mode 100644
index 0000000..86e1417
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt
@@ -0,0 +1,32 @@
+package com.hsLink.hslink.presentation.community.navigation.post
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.navigation.NavController
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.NavOptions
+import androidx.navigation.compose.composable
+import com.hsLink.hslink.core.navigation.Route
+import com.hsLink.hslink.presentation.community.screen.post.CommunityPostRoute
+import kotlinx.serialization.Serializable
+
+fun NavController.navigateToCommunityPost(
+ postId: String,
+ navOptions: NavOptions? = null
+) {
+ navigate(CommunityPost(postId), navOptions)
+}
+
+fun NavGraphBuilder.communityPostNavGraph(
+ padding: PaddingValues,
+ navigateUp: () -> Unit,
+) {
+ composable {
+ CommunityPostRoute(
+ paddingValues = padding,
+ navigateUp = navigateUp
+ )
+ }
+}
+
+@Serializable
+data class CommunityPost(val postId: String) : Route
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/write/CommunityWriteNavigation.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/write/CommunityWriteNavigation.kt
new file mode 100644
index 0000000..17e2482
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/navigation/write/CommunityWriteNavigation.kt
@@ -0,0 +1,31 @@
+package com.hsLink.hslink.presentation.community.navigation.write
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.navigation.NavController
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.NavOptions
+import androidx.navigation.compose.composable
+import com.hsLink.hslink.core.navigation.Route
+import com.hsLink.hslink.presentation.community.screen.write.CommunityWritingRoute
+import kotlinx.serialization.Serializable
+
+fun NavController.navigateToWriteCommunity(navOptions: NavOptions? = null) {
+ navigate(CommunityWrite, navOptions)
+}
+
+fun NavGraphBuilder.communityWriteNavGraph(
+ padding: PaddingValues,
+ navigateUp: () -> Unit,
+ navigateToCommunity: () -> Unit,
+) {
+ composable {
+ CommunityWritingRoute(
+ paddingValues = padding,
+ navigateUp = navigateUp,
+ navigateToCommunity = navigateToCommunity
+ )
+ }
+}
+
+@Serializable
+data object CommunityWrite : Route
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt
new file mode 100644
index 0000000..aec5f31
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt
@@ -0,0 +1,228 @@
+package com.hsLink.hslink.presentation.community.screen.main
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.component.HsLinkTopBar
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.core.util.noRippleClickable
+import com.hsLink.hslink.presentation.community.component.CommunityTab
+import com.hsLink.hslink.presentation.community.component.CommunityTabLayout
+import com.hsLink.hslink.presentation.home.component.CommunityCardItem
+
+data class CommunityPost(
+ val id: String,
+ val userName: String,
+ val userMajor: String,
+ val userInfo: String,
+)
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewCommunityScreen() {
+ HsLinkTheme {
+ CommunityScreen(
+ paddingValues = PaddingValues(),
+ navigateUp = {},
+ navigateWriteCommunity = {},
+ onClick = {},
+ navigateToPost = {}
+ )
+ }
+}
+
+@Composable
+fun CommunityRoute(
+ paddingValues: PaddingValues,
+ navigateUp: () -> Unit,
+ navigateWriteCommunity: () -> Unit,
+ navigateToPost: (String) -> Unit,
+) {
+ CommunityScreen(
+ paddingValues = paddingValues,
+ navigateUp = navigateUp,
+ navigateWriteCommunity = navigateWriteCommunity,
+ onClick = {},
+ navigateToPost = navigateToPost
+ )
+}
+
+@Composable
+fun CommunityScreen(
+ paddingValues: PaddingValues,
+ navigateUp: () -> Unit,
+ navigateWriteCommunity: () -> Unit,
+ onClick: () -> Unit,
+ navigateToPost: (String) -> Unit,
+ modifier: Modifier = Modifier,
+
+ ) {
+ var selectedTab by remember { mutableStateOf(CommunityTab.Popular) }
+
+ val posts = remember(selectedTab) {
+ when (selectedTab) {
+ CommunityTab.Popular -> listOf(
+ CommunityPost("1", "인기글 작성자1", "컴퓨터공학과", "인기글 내용입니다"),
+ CommunityPost("2", "인기글 작성자2", "경영학과", "좋아요가 많은 글"),
+ CommunityPost("3", "인기글 작성자3", "디자인학과", "핫한 글입니다"),
+ )
+
+ CommunityTab.Free -> listOf(
+ CommunityPost("4", "자유 작성자1", "전자공학과", "자유게시판 글1"),
+ CommunityPost("5", "자유 작성자2", "수학과", "자유게시판 글2"),
+ CommunityPost("6", "자유 작성자3", "물리학과", "자유게시판 글3"),
+ )
+
+ CommunityTab.Promotion -> listOf(
+ CommunityPost("7", "홍보 작성자1", "마케팅학과", "동아리 홍보합니다"),
+ CommunityPost("8", "홍보 작성자2", "광고홍보학과", "행사 알림"),
+ CommunityPost("9", "홍보 작성자3", "경제학과", "스터디 모집"),
+ )
+
+ CommunityTab.Notice -> listOf(
+ CommunityPost("10", "관리자1", "학생처", "중요 공지사항"),
+ CommunityPost("11", "관리자2", "교무처", "학사 일정 안내"),
+ CommunityPost("12", "관리자3", "총학생회", "필독 공지"),
+ )
+ }
+ }
+
+ Column(
+ modifier = modifier
+ .fillMaxSize()
+ .background(color = HsLinkTheme.colors.Common)
+ .padding(paddingValues)
+ ) {
+ HsLinkTopBar(
+ modifier = Modifier
+ .padding(start = 12.dp),
+ title = {
+ Image(
+ painter = painterResource(id = R.drawable.img_home_logo),
+ contentDescription = null,
+ modifier = Modifier
+ .height(48.dp)
+ .width(92.dp),
+ contentScale = ContentScale.FillBounds,
+ )
+ },
+ rightIconFirst = null,
+ rightIconSecond = null,
+ leftIcon = null
+ )
+
+ CommunityTabLayout(
+ selectedTab = selectedTab,
+ onTabSelected = { tab ->
+ selectedTab = tab
+ }
+ )
+
+ Box(
+ modifier = Modifier.fillMaxHeight()
+ ) {
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ contentPadding = PaddingValues(
+ start = 16.dp,
+ end = 16.dp,
+ top = 16.dp,
+ bottom = 80.dp
+ ),
+ verticalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ items(
+ items = posts,
+ key = { it.id }
+ ) { post ->
+ CommunityCardItem(
+ userName = post.userName,
+ userMajor = post.userMajor,
+ userInfo = post.userInfo,
+ onClick = { navigateToPost(post.id) }
+ )
+ }
+ }
+
+ CommunityFloatingButton(
+ onClick = navigateWriteCommunity,
+ modifier = Modifier
+ .align(Alignment.BottomCenter)
+ .padding(bottom = 16.dp)
+ )
+ }
+ }
+}
+
+@Composable
+private fun CommunityFloatingButton(
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Row(
+ modifier = modifier
+ .shadow(
+ elevation = 3.dp,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .background(color = HsLinkTheme.colors.Common, shape = RoundedCornerShape(6.dp))
+ .border(
+ width = 1.dp,
+ color = HsLinkTheme.colors.Grey200,
+ shape = RoundedCornerShape(6.dp)
+ )
+ .noRippleClickable(onClick = onClick)
+ .padding(horizontal = 16.dp, vertical = 9.dp),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Icon(
+ imageVector = ImageVector.vectorResource(id = R.drawable.ic_community_post),
+ contentDescription = null,
+ tint = Color.Unspecified
+ )
+
+ Spacer(modifier = Modifier.width(8.dp))
+
+ Text(
+ text = "글쓰기",
+ color = HsLinkTheme.colors.Grey500,
+ style = HsLinkTheme.typography.btm_M,
+
+ )
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt
new file mode 100644
index 0000000..9c7dcee
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt
@@ -0,0 +1,232 @@
+package com.hsLink.hslink.presentation.community.screen.post
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.component.HsLinkDialog
+import com.hsLink.hslink.core.designsystem.component.HsLinkTopBar
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.data.local.Comment
+import com.hsLink.hslink.data.local.PostDetail
+import com.hsLink.hslink.presentation.community.component.CommentInput
+import com.hsLink.hslink.presentation.community.component.CommentItem
+import com.hsLink.hslink.presentation.community.component.EmptyComment
+import com.hsLink.hslink.presentation.community.component.PostContent
+import com.hsLink.hslink.presentation.community.component.PostHeader
+
+
+@Preview(showBackground = true)
+@Composable
+private fun CommunityPostScreenPreview() {
+ HsLinkTheme {
+ CommunityPostScreen(
+ paddingValues = PaddingValues(),
+ navigateUp = {}
+ )
+ }
+}
+
+@Composable
+fun CommunityPostRoute(
+ paddingValues: PaddingValues,
+ navigateUp: () -> Unit,
+) {
+ CommunityPostScreen(
+ paddingValues = paddingValues,
+ navigateUp = navigateUp
+ )
+}
+
+@Composable
+fun CommunityPostScreen(
+ paddingValues: PaddingValues,
+ navigateUp: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+
+ val postDetail = remember {
+ PostDetail(
+ id = "1",
+ authorName = "송효재",
+ authorMajor = "재직중",
+ boardType = "자유게시판",
+ timeAgo = "21학번",
+ title = "추천 채용 한성 IT 추천 채용 공고 - 네이버 영업직 구합니다.",
+ content = "제가 다니고 있는 한성 it에서 추천 채용이 올라와 공유드립니다. 이미지 첨고해주세요",
+ isMyPost = true,
+ comments = listOf(
+ Comment(
+ id = "1",
+ authorName = "송효재",
+ timeAgo = "21학번",
+ content = "자기소개서 어떻게 작성하셨나요? 주로 보는 인재상이 있는지 궁금합니다.",
+ isMyComment = true
+ ),
+ Comment(
+ id = "2",
+ authorName = "김철수",
+ timeAgo = "20학번",
+ content = "좋은 정보 감사합니다!",
+ isMyComment = false
+ )
+ )
+ )
+ }
+
+ var commentText by remember { mutableStateOf("") }
+ var showDeleteDialog by remember { mutableStateOf(false) }
+ var showDeleteCommentDialog by remember { mutableStateOf(false) }
+ var selectedCommentId by remember { mutableStateOf(null) }
+
+ Box(
+ modifier = modifier
+ .fillMaxSize()
+ .background(HsLinkTheme.colors.Common)
+ .padding(paddingValues)
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(HsLinkTheme.colors.Common)
+ ) {
+ HsLinkTopBar(
+ title = {
+ Text(
+ text = "게시글",
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_20Strong
+ )
+ },
+ leftIcon = R.drawable.ic_community_post_leftarrow,
+ onLeftIconClick = navigateUp,
+ rightIconSecond = if (postDetail.isMyPost) R.drawable.ic_community_kebab else null,
+ onRightIconSecondClick = {
+ if (postDetail.isMyPost) {
+ showDeleteDialog = true
+ }
+ }
+ )
+
+ HorizontalDivider(
+ thickness = 1.dp,
+ color = HsLinkTheme.colors.Grey100
+ )
+
+ LazyColumn(
+ modifier = Modifier
+ .weight(1f)
+ .imePadding()
+ ) {
+ item {
+ PostHeader(
+ authorName = postDetail.authorName,
+ authorMajor = postDetail.authorMajor,
+ boardType = postDetail.boardType,
+ timeAgo = postDetail.timeAgo
+ )
+ }
+
+ item {
+ PostContent(
+ title = postDetail.title,
+ content = postDetail.content
+ )
+ }
+
+ item {
+ HorizontalDivider(
+ thickness = 8.dp,
+ color = HsLinkTheme.colors.Grey100
+ )
+ }
+
+ if (postDetail.comments.isEmpty()) {
+ item {
+ EmptyComment()
+ }
+ } else {
+ items(
+ items = postDetail.comments,
+ key = { it.id }
+ ) { comment ->
+ CommentItem(
+ authorName = comment.authorName,
+ timeAgo = comment.timeAgo,
+ content = comment.content,
+ isMyComment = comment.isMyComment,
+ onDeleteClick = {
+ selectedCommentId = comment.id
+ showDeleteCommentDialog = true
+ }
+ )
+
+ HorizontalDivider(
+ thickness = 1.dp,
+ color = HsLinkTheme.colors.Grey100
+ )
+ }
+ }
+ }
+
+ CommentInput(
+ value = commentText,
+ onValueChange = { commentText = it },
+ onSendClick = {
+ // TODO: 댓글 전송 로직
+ commentText = ""
+ }
+ )
+ }
+ }
+
+ if (showDeleteDialog) {
+ HsLinkDialog(
+ title = "게시글을 삭제하시겠습니까?",
+ message = "삭제된 게시글은 복구할 수 없습니다.",
+ confirmText = "삭제하기",
+ dismissText = "취소",
+ onConfirm = {
+ showDeleteDialog = false
+ // TODO: 게시글 삭제 로직
+ navigateUp()
+ },
+ onDismiss = {
+ showDeleteDialog = false
+ }
+ )
+ }
+
+ if (showDeleteCommentDialog) {
+ HsLinkDialog(
+ title = "댓글을 삭제하시겠습니까?",
+ message = "삭제된 댓글은 복구할 수 없습니다.",
+ confirmText = "삭제하기",
+ dismissText = "취소",
+ onConfirm = {
+ showDeleteCommentDialog = false
+ // TODO: 댓글 삭제 로직 (selectedCommentId 사용)
+ },
+ onDismiss = {
+ showDeleteCommentDialog = false
+ selectedCommentId = null
+ }
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt b/app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt
new file mode 100644
index 0000000..f4a0050
--- /dev/null
+++ b/app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt
@@ -0,0 +1,254 @@
+package com.hsLink.hslink.presentation.community.screen.write
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.hsLink.hslink.R
+import com.hsLink.hslink.core.designsystem.component.HsLinkDialog
+import com.hsLink.hslink.core.designsystem.component.HsLinkTextField
+import com.hsLink.hslink.core.designsystem.component.HsLinkTopBar
+import com.hsLink.hslink.core.designsystem.theme.HsLinkTheme
+import com.hsLink.hslink.presentation.community.component.BoardSelectionField
+import com.hsLink.hslink.presentation.community.component.BoardType
+import com.hsLink.hslink.presentation.community.component.CommunityWriteButton
+
+@Preview(showBackground = true)
+@Composable
+private fun CommunityWritingScreenPreview() {
+ HsLinkTheme {
+ CommunityWritingScreen(
+ paddingValues = PaddingValues(),
+ navigateUp = {},
+ navigateToCommunity = {}
+ )
+ }
+}
+
+@Composable
+fun CommunityWritingRoute(
+ paddingValues: PaddingValues,
+ navigateUp: () -> Unit,
+ navigateToCommunity: () -> Unit,
+) {
+ CommunityWritingScreen(
+ paddingValues = paddingValues,
+ navigateUp = navigateUp,
+ navigateToCommunity = navigateToCommunity
+ )
+}
+
+@Composable
+fun CommunityWritingScreen(
+ paddingValues: PaddingValues,
+ navigateUp: () -> Unit,
+ navigateToCommunity: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ var selectedBoardType by remember { mutableStateOf(null) }
+ var selectedBoardText by remember { mutableStateOf("") }
+ var title by remember { mutableStateOf("") }
+ var content by remember { mutableStateOf("") }
+
+ var isBoardExpanded by remember { mutableStateOf(false) }
+ var isBoardFocused by remember { mutableStateOf(false) }
+ var isTitleFocused by remember { mutableStateOf(false) }
+ var isContentFocused by remember { mutableStateOf(false) }
+
+ var showExitDialog by remember { mutableStateOf(false) }
+ var showUploadDialog by remember { mutableStateOf(false) }
+
+ val isDone = selectedBoardType != null &&
+ title.isNotBlank() &&
+ content.isNotBlank()
+
+ Column(
+ modifier = modifier
+ .fillMaxSize()
+ .background(color = HsLinkTheme.colors.Common)
+ .padding(paddingValues)
+ .imePadding()
+ ) {
+ HsLinkTopBar(
+ modifier = Modifier
+ .padding(start = 12.dp),
+ title = {
+ Text(
+ text = "글쓰기",
+ color = HsLinkTheme.colors.Grey600,
+ style = HsLinkTheme.typography.title_20Strong
+ )
+ },
+ rightIconSecond = R.drawable.ic_community_write_close,
+ onRightIconSecondClick = { showExitDialog = true }
+ )
+
+ HorizontalDivider(
+ thickness = 1.dp,
+ color = HsLinkTheme.colors.Grey100
+ )
+
+ Column(
+ modifier = Modifier
+ .weight(1f)
+ .verticalScroll(rememberScrollState())
+ .background(color = HsLinkTheme.colors.Common)
+ .padding(16.dp),
+ verticalArrangement = Arrangement.spacedBy(16.dp)
+ ) {
+ Column(
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ Text(
+ text = "게시판 선택",
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_14Strong
+ )
+
+ BoardSelectionField(
+ selectedBoard = selectedBoardText,
+ isExpanded = isBoardExpanded,
+ onExpandedChange = { isBoardExpanded = it },
+ onBoardSelected = { board ->
+ selectedBoardType = board
+ selectedBoardText = board.displayName
+ },
+ isFocused = isBoardFocused,
+ onFocusChanged = { isBoardFocused = it },
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+
+ Column(
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ Text(
+ text = "제목",
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_14Strong
+ )
+
+ val maxTitleLength = 30
+
+ HsLinkTextField(
+ value = title,
+ placeholder = "제목을 입력해주세요",
+ onValueChanged = {
+ if (it.length <= maxTitleLength) {
+ title = it
+ }
+ },
+ borderColor = if (isTitleFocused) {
+ HsLinkTheme.colors.DeepBlue500
+ } else {
+ HsLinkTheme.colors.Grey200
+ },
+ backgroundColor = HsLinkTheme.colors.Common,
+ onFocusChanged = { isTitleFocused = it },
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+
+ Column(
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ Text(
+ text = "내용",
+ color = HsLinkTheme.colors.Grey700,
+ style = HsLinkTheme.typography.title_14Strong
+ )
+
+ val maxContentLength = 500
+
+ HsLinkTextField(
+ value = content,
+ placeholder = "내용을 입력해주세요",
+ onValueChanged = {
+ if (it.length <= maxContentLength) {
+ content = it
+ }
+ },
+ borderColor = if (isContentFocused) {
+ HsLinkTheme.colors.DeepBlue500
+ } else {
+ HsLinkTheme.colors.Grey200
+ },
+ backgroundColor = HsLinkTheme.colors.Common,
+ onFocusChanged = { isContentFocused = it },
+ singleLine = false,
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ Text(
+ text = "${content.length}/$maxContentLength",
+ color = if (content.length >= maxContentLength) {
+ HsLinkTheme.colors.Red500
+ } else {
+ HsLinkTheme.colors.Grey400
+ },
+ style = HsLinkTheme.typography.caption_12Normal,
+ modifier = Modifier.align(Alignment.End)
+ )
+ }
+ }
+
+ CommunityWriteButton(
+ isDone = isDone,
+ onClick = {
+ if (isDone) {
+ showUploadDialog = true
+ }
+ },
+ modifier = Modifier.padding(16.dp)
+ )
+ }
+
+ if (showExitDialog) {
+ HsLinkDialog(
+ title = "글쓰기를 종료하시겠습니까?",
+ message = "작성 중인 내용이 저장되지 않습니다.",
+ confirmText = "나가기",
+ dismissText = "취소하기",
+ onConfirm = {
+ showExitDialog = false
+ navigateUp()
+ },
+ onDismiss = {
+ showExitDialog = false
+ }
+ )
+ }
+
+ if (showUploadDialog) {
+ HsLinkDialog(
+ title = "게시글을 업로드하시겠습니까?",
+ message = "작성한 내용이 게시판에 공개됩니다.",
+ confirmText = "업로드하기",
+ dismissText = "취소하기",
+ onConfirm = {
+ showUploadDialog = false
+ navigateToCommunity()
+ },
+ onDismiss = {
+ showUploadDialog = false
+ }
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt b/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt
index e77eaff..f43f63c 100644
--- a/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt
+++ b/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt
@@ -4,7 +4,9 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
-import com.hsLink.hslink.presentation.home.navigation.communityNavGraph
+import com.hsLink.hslink.presentation.community.navigation.main.communityNavGraph
+import com.hsLink.hslink.presentation.community.navigation.post.communityPostNavGraph
+import com.hsLink.hslink.presentation.community.navigation.write.communityWriteNavGraph
import com.hsLink.hslink.presentation.home.navigation.homeNavGraph
import com.hsLink.hslink.presentation.home.navigation.searchNavGraph
import com.hsLink.hslink.presentation.mypage.navigation.mypageNavGraph
@@ -23,7 +25,23 @@ fun MainNavHost(
) {
homeNavGraph(padding)
searchNavGraph(padding)
- communityNavGraph(padding)
+ communityNavGraph(
+ padding,
+ navigateUp = navigator::navigateUp,
+ navigateToWriting = navigator::navigateWriteCommunity,
+ navigateToPost = navigator::navigateToCommunityPost
+ )
mypageNavGraph(padding)
+
+ communityWriteNavGraph(
+ padding = padding,
+ navigateUp = navigator::navigateUp,
+ navigateToCommunity = navigator::navigateToCommunity
+ )
+
+ communityPostNavGraph(
+ padding = padding,
+ navigateUp = navigator::navigateUp
+ )
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt b/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt
index a9fd785..bddfade 100644
--- a/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt
+++ b/app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt
@@ -5,13 +5,16 @@ import androidx.compose.runtime.remember
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavHostController
+import androidx.navigation.NavOptions
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.hsLink.hslink.presentation.home.navigation.Home
-import com.hsLink.hslink.presentation.home.navigation.navigateToCommunity
+import com.hsLink.hslink.presentation.community.navigation.main.navigateToCommunity
+import com.hsLink.hslink.presentation.community.navigation.post.navigateToCommunityPost
import com.hsLink.hslink.presentation.home.navigation.navigateToHome
import com.hsLink.hslink.presentation.home.navigation.navigateToSearch
+import com.hsLink.hslink.presentation.community.navigation.write.navigateToWriteCommunity
import com.hsLink.hslink.presentation.mypage.navigation.navigateToMypage
class MainNavigator(
@@ -51,7 +54,19 @@ class MainNavigator(
}
fun navigateUp() {
- navController::navigateUp
+ navController.navigateUp()
+ }
+
+ fun navigateWriteCommunity(navOptions: NavOptions? = null) {
+ navController.navigateToWriteCommunity(navOptions)
+ }
+
+ fun navigateToCommunity(navOptions: NavOptions? = null) {
+ navController.navigateToCommunity(navOptions)
+ }
+
+ fun navigateToCommunityPost(postId: String, navOptions: NavOptions? = null) {
+ navController.navigateToCommunityPost(postId, navOptions)
}
@Composable
diff --git a/app/src/main/java/com/hsLink/hslink/presentation/main/MainTab.kt b/app/src/main/java/com/hsLink/hslink/presentation/main/MainTab.kt
index 05d3280..8f92f96 100644
--- a/app/src/main/java/com/hsLink/hslink/presentation/main/MainTab.kt
+++ b/app/src/main/java/com/hsLink/hslink/presentation/main/MainTab.kt
@@ -5,7 +5,7 @@ import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import com.hsLink.hslink.R
import com.hsLink.hslink.core.navigation.MainTabRoute
-import com.hsLink.hslink.presentation.home.navigation.Community
+import com.hsLink.hslink.presentation.community.navigation.main.Community
import com.hsLink.hslink.presentation.home.navigation.Home
import com.hsLink.hslink.presentation.home.navigation.Search
import com.hsLink.hslink.presentation.mypage.navigation.Mypage
diff --git a/app/src/main/res/drawable/ic_community_arrow_down.xml b/app/src/main/res/drawable/ic_community_arrow_down.xml
new file mode 100644
index 0000000..72b8356
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_arrow_down.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_arrow_up.xml b/app/src/main/res/drawable/ic_community_arrow_up.xml
new file mode 100644
index 0000000..1be87b0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_arrow_up.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_button.xml b/app/src/main/res/drawable/ic_community_button.xml
new file mode 100644
index 0000000..e986c2c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_button.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_kebab.xml b/app/src/main/res/drawable/ic_community_kebab.xml
new file mode 100644
index 0000000..d23deaf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_kebab.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_post.xml b/app/src/main/res/drawable/ic_community_post.xml
new file mode 100644
index 0000000..466c559
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_post.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_post_leftarrow.xml b/app/src/main/res/drawable/ic_community_post_leftarrow.xml
new file mode 100644
index 0000000..3161228
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_post_leftarrow.xml
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_post_send.xml b/app/src/main/res/drawable/ic_community_post_send.xml
new file mode 100644
index 0000000..46424c7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_post_send.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_community_write_close.xml b/app/src/main/res/drawable/ic_community_write_close.xml
new file mode 100644
index 0000000..11ec82f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_community_write_close.xml
@@ -0,0 +1,9 @@
+
+
+