From 0d5025bb92c21b02f37de1d78a1002ccaf1a1b5b Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 13:30:38 +0900 Subject: [PATCH 01/50] =?UTF-8?q?[refactor]:=20group=20vote=20button=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EA=B5=AC=EC=A1=B0=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/buttons/GroupVoteButton.kt | 59 ++++++++++++------- .../texthip/thip/ui/common/cards/CardVote.kt | 49 +++++++++++---- .../thip/ui/group/room/mock/VoteData.kt | 5 +- 3 files changed, 77 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt index 08a5a6f0..4da40172 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt @@ -25,6 +25,7 @@ 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.texthip.thip.ui.group.note.mock.VoteItem import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -32,21 +33,18 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun GroupVoteButton( modifier: Modifier = Modifier, - options: List, - voteResults: List, - selectedIndex: Int?, // 외부에서 전달받은 선택 상태 - onOptionSelected: (Int?) -> Unit // 클릭 시 선택 변경 콜백 + voteItems: List, + selectedIndex: Int?, // 선택한 인덱스 + hasVoted: Boolean = false, // 투표 여부 + onOptionSelected: (Int?) -> Unit ) { - val hasVoted = selectedIndex != null - Column( - modifier = modifier - .fillMaxWidth(), + modifier = modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(10.dp) ) { - options.forEachIndexed { index, option -> + voteItems.forEachIndexed { index, item -> val isSelected = selectedIndex == index - val votePercent = if (hasVoted) voteResults.getOrNull(index)?.coerceIn(0, 100) ?: 0 else 0 + val votePercent = if (hasVoted) item.percentage.coerceIn(0, 100) else 0 val animatedPercent by animateFloatAsState( targetValue = votePercent / 100f, @@ -75,7 +73,7 @@ fun GroupVoteButton( .height(44.dp) .clickable { if (isSelected) { - onOptionSelected(null) // -1 → 취소 의미 + onOptionSelected(null) } else { onOptionSelected(index) } @@ -101,13 +99,13 @@ fun GroupVoteButton( horizontalArrangement = Arrangement.SpaceBetween ) { Text( - text = "${index + 1}. $option", + text = "${index + 1}. ${item.itemName}", color = textColor, style = fontStyle ) if (hasVoted) { Text( - text = "$votePercent%", + text = "${item.percentage}%", color = textColor, style = fontStyle ) @@ -121,18 +119,37 @@ fun GroupVoteButton( @Preview @Composable private fun GroupVoteButtonPreview() { - val options = listOf("밥", "국수", "고기") - val results = listOf(20, 30, 50) var selected by remember { mutableStateOf(null) } + var voteItems by remember { + mutableStateOf( + listOf( + VoteItem(1, "밥", 25, false), + VoteItem(2, "국수", 35, false), + VoteItem(3, "고기", 40, false) + ) + ) + } - Column( - modifier = Modifier.fillMaxSize() - ) { + val hasVoted = voteItems.any { it.isVoted } + + Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { GroupVoteButton( - options = options, - voteResults = results, + voteItems = voteItems, selectedIndex = selected, - onOptionSelected = { selected = it } + hasVoted = hasVoted, + onOptionSelected = { + if (selected == it) { + // ✅ 이미 선택한 항목을 다시 클릭한 경우: 취소 처리 + selected = null + voteItems = voteItems.map { it.copy(isVoted = false) } + } else { + // ✅ 새로운 항목 선택 + selected = it + voteItems = voteItems.mapIndexed { index, item -> + item.copy(isVoted = index == it) + } + } + } ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt index e8c7c5ec..4cad7a04 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt @@ -16,12 +16,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.remember +import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.GroupVoteButton +import com.texthip.thip.ui.group.note.mock.VoteItem import com.texthip.thip.ui.group.room.mock.VoteData import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -33,8 +35,11 @@ fun CardVote( val pageCount = voteData.size val pagerState = rememberPagerState(pageCount = { pageCount }) - // 각 투표에 따라 투표한거 기록 + // 각 페이지별 상태 기억: 선택 인덱스, 선택 여부 포함한 voteItems val selectedIndexes = remember { mutableStateMapOf() } + val voteItemStates = remember { + voteData.map { it.voteItems.toMutableStateList() }.toMutableStateList() + } Column( modifier = Modifier @@ -50,29 +55,35 @@ fun CardVote( modifier = Modifier.padding(horizontal = 12.dp) ) - HorizontalPager( state = pagerState, modifier = Modifier.fillMaxWidth() ) { page -> - val item = voteData[page] + val voteItems = voteItemStates[page] val selectedIndex = selectedIndexes[page] + val hasVoted = voteItems.any { it.isVoted } Column( modifier = Modifier.padding(horizontal = 12.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { Text( - text = item.description, + text = voteData[page].description, style = typography.info_m500_s12, color = colors.White, ) GroupVoteButton( - options = item.options, - voteResults = item.votes, + voteItems = voteItems, selectedIndex = selectedIndex, - onOptionSelected = { selectedIndexes[page] = it } + hasVoted = hasVoted, + onOptionSelected = { index -> + selectedIndexes[page] = if (selectedIndex == index) null else index + + voteItemStates[page] = voteItems.mapIndexed { i, item -> + item.copy(isVoted = i == index && selectedIndex != index) + }.toMutableStateList() + } ) } } @@ -101,18 +112,30 @@ private fun CardVotePreview() { val mockVoteData = listOf( VoteData( description = "투표 내용입니다...", - options = listOf("김땡땡", "이땡땡", "박땡땡", "최땡땡", "정땡땡"), - votes = listOf(50, 10, 20, 15, 5) + voteItems = listOf( + VoteItem(1, "김땡땡", 50, false), + VoteItem(2, "이땡땡", 10, false), + VoteItem(3, "박땡땡", 20, false), + VoteItem(4, "최땡땡", 15, false), + VoteItem(5, "정땡땡", 5, false) + ) ), VoteData( description = "옆으로 넘긴 다른 투표 01", - options = listOf("어쩌구", "저쩌구", "삼번", "사번"), - votes = listOf(25, 45, 20, 10) + voteItems = listOf( + VoteItem(1, "어쩌구", 25, false), + VoteItem(2, "저쩌구", 45, false), + VoteItem(3, "삼번", 20, false), + VoteItem(4, "사번", 10, false) + ) ), VoteData( description = "옆으로 넘긴 다른 투표 02", - options = listOf("투표 제목과 항목 버튼이 가로 스크롤되고", "아래 캐러셀 닷은", "위치 그대로, 강조점만 바뀌도록."), - votes = listOf(40, 35, 25) + voteItems = listOf( + VoteItem(1, "투표 제목과 항목 버튼이 가로 스크롤되고", 40, false), + VoteItem(2, "아래 캐러셀 닷은", 35, false), + VoteItem(3, "위치 그대로, 강조점만 바뀌도록.", 25, false) + ) ) ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt index 36f22a84..7e8f0d0e 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt @@ -1,7 +1,8 @@ package com.texthip.thip.ui.group.room.mock +import com.texthip.thip.ui.group.note.mock.VoteItem + data class VoteData( val description: String, - val options: List, - val votes: List + val voteItems: List ) \ No newline at end of file From 0231fc7f2f6ae744ee6d52b5e252af7d6f07ee52 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 14:19:33 +0900 Subject: [PATCH 02/50] =?UTF-8?q?[refactor]:=20data=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/common/cards/CardVote.kt | 32 +------------------ .../ui/group/room/component/GroupRoomBody.kt | 20 +----------- .../thip/ui/group/room/mock/VoteData.kt | 30 +++++++++++++++++ .../ui/group/room/screen/GroupRoomScreen.kt | 24 ++------------ 4 files changed, 34 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt index 4cad7a04..12df707f 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt @@ -23,8 +23,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.GroupVoteButton -import com.texthip.thip.ui.group.note.mock.VoteItem import com.texthip.thip.ui.group.room.mock.VoteData +import com.texthip.thip.ui.group.room.mock.mockVoteData import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -109,35 +109,5 @@ fun CardVote( @Preview @Composable private fun CardVotePreview() { - val mockVoteData = listOf( - VoteData( - description = "투표 내용입니다...", - voteItems = listOf( - VoteItem(1, "김땡땡", 50, false), - VoteItem(2, "이땡땡", 10, false), - VoteItem(3, "박땡땡", 20, false), - VoteItem(4, "최땡땡", 15, false), - VoteItem(5, "정땡땡", 5, false) - ) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 01", - voteItems = listOf( - VoteItem(1, "어쩌구", 25, false), - VoteItem(2, "저쩌구", 45, false), - VoteItem(3, "삼번", 20, false), - VoteItem(4, "사번", 10, false) - ) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 02", - voteItems = listOf( - VoteItem(1, "투표 제목과 항목 버튼이 가로 스크롤되고", 40, false), - VoteItem(2, "아래 캐러셀 닷은", 35, false), - VoteItem(3, "위치 그대로, 강조점만 바뀌도록.", 25, false) - ) - ) - ) - CardVote(voteData = mockVoteData) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt index 0c37743e..9d8a2600 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt @@ -14,7 +14,7 @@ import com.texthip.thip.ui.common.cards.CardChat import com.texthip.thip.ui.common.cards.CardNote import com.texthip.thip.ui.common.cards.CardVote import com.texthip.thip.ui.group.room.mock.GroupRoomBodyData -import com.texthip.thip.ui.group.room.mock.VoteData +import com.texthip.thip.ui.group.room.mock.mockVoteData @Composable fun GroupRoomBody( @@ -49,24 +49,6 @@ fun GroupRoomBody( @Preview @Composable private fun GroupRoomBodyPreview() { - val mockVoteData = listOf( - VoteData( - description = "투표 내용입니다...", - options = listOf("김땡땡", "이땡땡", "박땡땡", "최땡땡", "정땡땡"), - votes = listOf(50, 10, 20, 15, 5) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 01", - options = listOf("어쩌구", "저쩌구", "삼번", "사번"), - votes = listOf(25, 45, 20, 10) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 02", - options = listOf("투표 제목과 항목 버튼이 가로 스크롤되고", "아래 캐러셀 닷은", "위치 그대로, 강조점만 바뀌도록."), - votes = listOf(40, 35, 25) - ) - ) - GroupRoomBody( data = GroupRoomBodyData( bookTitle = "호르몬 체인지", diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt index 7e8f0d0e..638cd8f7 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt @@ -5,4 +5,34 @@ import com.texthip.thip.ui.group.note.mock.VoteItem data class VoteData( val description: String, val voteItems: List +) + +val mockVoteData = listOf( + VoteData( + description = "투표 내용입니다...", + voteItems = listOf( + VoteItem(1, "김땡땡", 50, false), + VoteItem(2, "이땡땡", 10, false), + VoteItem(3, "박땡땡", 20, false), + VoteItem(4, "최땡땡", 15, false), + VoteItem(5, "정땡땡", 5, false) + ) + ), + VoteData( + description = "옆으로 넘긴 다른 투표 01", + voteItems = listOf( + VoteItem(1, "어쩌구", 25, false), + VoteItem(2, "저쩌구", 45, false), + VoteItem(3, "삼번", 20, false), + VoteItem(4, "사번", 10, false) + ) + ), + VoteData( + description = "옆으로 넘긴 다른 투표 02", + voteItems = listOf( + VoteItem(1, "투표 제목과 항목 버튼이 가로 스크롤되고", 40, false), + VoteItem(2, "아래 캐러셀 닷은", 35, false), + VoteItem(3, "위치 그대로, 강조점만 바뀌도록.", 25, false) + ) + ) ) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt index d9456c0e..36c5d66b 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt @@ -31,7 +31,7 @@ import com.texthip.thip.ui.group.room.component.GroupRoomBody import com.texthip.thip.ui.group.room.component.GroupRoomHeader import com.texthip.thip.ui.group.room.mock.GroupRoomBodyData import com.texthip.thip.ui.group.room.mock.GroupRoomHeaderData -import com.texthip.thip.ui.group.room.mock.VoteData +import com.texthip.thip.ui.group.room.mock.mockVoteData import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors @@ -85,27 +85,7 @@ fun GroupRoomScreen() { bookAuthor = "최정화", currentPage = 100, percentage = 50, - voteList = listOf( - VoteData( - description = "투표 내용입니다...", - options = listOf("김땡땡", "이땡땡", "박땡땡", "최땡땡", "정땡땡"), - votes = listOf(50, 10, 20, 15, 5) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 01", - options = listOf("어쩌구", "저쩌구", "삼번", "사번"), - votes = listOf(25, 45, 20, 10) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 02", - options = listOf( - "투표 제목과 항목 버튼이 가로 스크롤되고", - "아래 캐러셀 닷은", - "위치 그대로, 강조점만 바뀌도록." - ), - votes = listOf(40, 35, 25) - ) - ) + voteList = mockVoteData ) ) } From d887ae5ffec6e4da95283695b37d32461375efa6 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 14:19:48 +0900 Subject: [PATCH 03/50] =?UTF-8?q?[ui]:=20vote=20comment=20card=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EC=9E=91=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group/note/component/VoteCommentCard.kt | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt new file mode 100644 index 00000000..719d1e23 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt @@ -0,0 +1,108 @@ +package com.texthip.thip.ui.group.note.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +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.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.ActionBarButton +import com.texthip.thip.ui.common.buttons.GroupVoteButton +import com.texthip.thip.ui.common.header.ProfileBar +import com.texthip.thip.ui.group.note.mock.GroupNoteVote +import com.texthip.thip.ui.group.note.mock.VoteItem +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun VoteCommentCard( + data: GroupNoteVote, +) { + var isLiked by remember { mutableStateOf(data.isLiked) } + var selected by remember { mutableStateOf(null) } + var voteItems by remember { mutableStateOf(data.voteItems) } + val hasVoted = voteItems.any { it.isVoted } + + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + ProfileBar( +// profileImage = data.profileImageUrl, + profileImage = painterResource(R.drawable.character_literature), + topText = data.nickName, + bottomText = data.page.toString() + stringResource(R.string.page), + bottomTextColor = colors.Purple, + showSubscriberInfo = false, +// hoursAgo = data.postDate + hoursAgo = data.postDate + ) + + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = data.content, + style = typography.feedcopy_r400_s14_h20, + color = colors.White, + ) + + GroupVoteButton( + voteItems = voteItems, + selectedIndex = selected, + hasVoted = hasVoted, + onOptionSelected = { + if (selected == it) { + selected = null + voteItems = voteItems.map { it.copy(isVoted = false) } + } else { + selected = it + voteItems = voteItems.mapIndexed { index, item -> + item.copy(isVoted = index == it) + } + } + } + ) + } + + ActionBarButton( + isLiked = isLiked, + likeCount = data.likeCount, + commentCount = data.commentCount, + onLikeClick = { + isLiked = !isLiked + }, + onCommentClick = { }, + ) + } +} + +@Preview +@Composable +private fun VoteCommentCardPreview() { + VoteCommentCard( + data = GroupNoteVote( + postDate = 12, + page = 12, + userId = 1, + nickName = "user.01", + profileImageUrl = "https://example.com/profile.jpg", + content = "3연에 나오는 심장은 무엇을 의미하는 걸까요?", + likeCount = 123, + commentCount = 123, + isLiked = true, + isWriter = false, + voteId = 1, + voteItems = listOf( + VoteItem(1, "김땡땡", 90, false), + VoteItem(2, "김땡땡", 10, false), + ) + ) + ) +} \ No newline at end of file From 8f22566be7d734ff906580e72ea6982f231c3262 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 14:38:50 +0900 Subject: [PATCH 04/50] =?UTF-8?q?[ui]:=20profilebar=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/texthip/thip/ui/common/header/ProfileBar.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt index 6c29cdb8..20c08449 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt @@ -9,7 +9,6 @@ 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.foundation.layout.width import androidx.compose.foundation.shape.CircleShape @@ -46,7 +45,6 @@ fun ProfileBar( Row( modifier = modifier .fillMaxWidth() - .padding( vertical = 12.dp) .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically ) { From d4d71cd8e20dc7d3e2bcafd9ddd632b4f9adee4f Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 14:45:30 +0900 Subject: [PATCH 05/50] =?UTF-8?q?[ui]:=20floating=20button=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/texthip/thip/ui/common/buttons/FloatingButton.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/FloatingButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/FloatingButton.kt index 976ae34d..db153970 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/FloatingButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/FloatingButton.kt @@ -24,13 +24,14 @@ import com.texthip.thip.ui.theme.ThipTheme.colors @Composable fun FloatingButton( + modifier: Modifier = Modifier, icon: Painter, onClick: () -> Unit = { } ) { var expanded by remember { mutableStateOf(false) } Box( - modifier = Modifier + modifier = modifier .fillMaxSize() .padding(end = 20.dp, bottom = 32.dp), contentAlignment = Alignment.BottomEnd @@ -45,7 +46,6 @@ fun FloatingButton( contentColor = colors.NeonGreen, shape = CircleShape, modifier = Modifier - .padding(16.dp) .size(56.dp) .border(width = 2.dp, color = colors.NeonGreen50, shape = CircleShape) ) { From a61981afadbc5baa8a03c3b80e2972c3b540024a Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 15:13:26 +0900 Subject: [PATCH 06/50] =?UTF-8?q?[ui]:=20=EA=B8=B0=EB=A1=9D=EC=9E=A5=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=9C=EC=9E=91=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../note/component/FilterHeaderSection.kt | 4 +- .../group/note/component/TextCommentCard.kt | 3 + .../thip/ui/group/note/mock/CommentData.kt | 63 ++++++++ .../ui/group/note/screen/GroupNoteScreen.kt | 148 ++++++++++++++++++ app/src/main/res/drawable/ic_information.xml | 27 ++++ app/src/main/res/values/strings.xml | 1 + 6 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt create mode 100644 app/src/main/res/drawable/ic_information.xml diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt index a2bba8dc..b1452684 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/FilterHeaderSection.kt @@ -38,7 +38,7 @@ fun FilterHeaderSection( Box( modifier = Modifier .fillMaxWidth() - .padding(20.dp), + .padding(horizontal = 20.dp), contentAlignment = Alignment.Center ) { Row( @@ -61,7 +61,7 @@ fun FilterHeaderSection( text = stringResource(R.string.view_by_all), isFilled = true, isSelected = isTotalSelected, - enabled = totalEnabled, // ✅ 추가된 enabled 인자 + enabled = totalEnabled, textStyle = typography.menu_r400_s14_h24, onClick = onTotalToggle ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt index 913276f9..34cf24f8 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt @@ -2,12 +2,14 @@ package com.texthip.thip.ui.group.note.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding 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.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -29,6 +31,7 @@ fun TextCommentCard( verticalArrangement = Arrangement.spacedBy(8.dp) ) { ProfileBar( + modifier = Modifier.padding(0.dp), // profileImage = data.profileImageUrl, profileImage = painterResource(R.drawable.character_literature), topText = data.nickName, diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt b/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt index 345cd846..668216cf 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt @@ -48,4 +48,67 @@ data class VoteItem( val itemName: String, val percentage: Int, val isVoted: Boolean +) + +val mockGroupNoteItems: List = listOf( + GroupNoteRecord( + page = 132, + postDate = 12, + userId = 1, + nickName = "user.01", + profileImageUrl = "https://example.com/profile.jpg", + content = "내 생각에 이 부분이 가장 어려운 것 같다. 비유도 난해하고 잘 이해가 가지 않는데 다른 메이트들은 어떻게 읽었나요?", + likeCount = 123, + commentCount = 123, + isLiked = true, + isWriter = false, + recordId = 1 + ), + GroupNoteVote( + page = 12, + postDate = 12, + userId = 1, + nickName = "user.01", + profileImageUrl = "https://example.com/profile.jpg", + content = "3연에 나오는 심장은 무엇을 의미하는 걸까요?", + likeCount = 123, + commentCount = 123, + isLiked = false, + isWriter = false, + voteId = 1, + voteItems = listOf( + VoteItem(1, "김땡땡", 90, false), + VoteItem(2, "김땡땡", 10, false) + ) + ), + GroupNoteRecord( + page = 132, + postDate = 12, + userId = 1, + nickName = "user.01", + profileImageUrl = "https://example.com/profile.jpg", + content = "공백 포함 글자 입력입니다.", + likeCount = 123, + commentCount = 123, + isLiked = false, + isWriter = true, + recordId = 1 + ), + GroupNoteVote( + page = 12, + postDate = 12, + userId = 1, + nickName = "user.01", + profileImageUrl = "https://example.com/profile.jpg", + content = "3연에 나오는 심장은 무엇을 의미하는 걸까요?", + likeCount = 123, + commentCount = 123, + isLiked = true, + isWriter = true, + voteId = 1, + voteItems = listOf( + VoteItem(1, "김땡땡", 90, false), + VoteItem(2, "김땡땡", 10, false) + ) + ) ) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt new file mode 100644 index 00000000..4e57c8ff --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt @@ -0,0 +1,148 @@ +package com.texthip.thip.ui.group.note.screen + +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.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.FilterButton +import com.texthip.thip.ui.common.buttons.FloatingButton +import com.texthip.thip.ui.common.header.HeaderMenuBarTab +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.group.note.component.FilterHeaderSection +import com.texthip.thip.ui.group.note.component.TextCommentCard +import com.texthip.thip.ui.group.note.component.VoteCommentCard +import com.texthip.thip.ui.group.note.mock.GroupNoteRecord +import com.texthip.thip.ui.group.note.mock.GroupNoteVote +import com.texthip.thip.ui.group.note.mock.mockGroupNoteItems +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun GroupNoteScreen() { + val tabs = listOf(stringResource(R.string.group_record), stringResource(R.string.my_record)) + var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) } + + var firstPage by rememberSaveable { mutableStateOf("") } + var lastPage by rememberSaveable { mutableStateOf("") } + var isTotalSelected by rememberSaveable { mutableStateOf(false) } + var totalEnabled by rememberSaveable { mutableStateOf(false) } + + var selectedFilter by rememberSaveable { mutableStateOf("최신순") } + val filters = listOf("최신순", "인기순", "댓글 많은 순") + + val filteredItems = when (selectedTabIndex) { + 0 -> mockGroupNoteItems.filter { !it.isWriter } // 다른 사람 기록 + 1 -> mockGroupNoteItems.filter { it.isWriter } // 내 기록 + else -> emptyList() + } + + Column(modifier = Modifier.fillMaxSize()) { + DefaultTopAppBar( + title = stringResource(R.string.record_book), + onLeftClick = {} + ) + + Column { + HeaderMenuBarTab( + titles = tabs, + selectedTabIndex = selectedTabIndex, + onTabSelected = { selectedTabIndex = it }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp) + ) + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp), + contentAlignment = Alignment.CenterStart + ) { + FilterButton( + modifier = Modifier + .fillMaxWidth() + .padding(end = 20.dp), + selectedOption = selectedFilter, + options = filters, + onOptionSelected = { selectedFilter = it } + ) + FilterHeaderSection( + firstPage = firstPage, + lastPage = lastPage, + isTotalSelected = isTotalSelected, + totalEnabled = totalEnabled, + onFirstPageChange = { firstPage = it }, + onLastPageChange = { lastPage = it }, + onTotalToggle = { isTotalSelected = !isTotalSelected }, + ) + } + + // 피드 리스트 영역 + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 82.dp) + .padding(20.dp), + verticalArrangement = Arrangement.spacedBy(32.dp) + ) { + item{ + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + Icon( + painterResource(R.drawable.ic_information), + contentDescription = null, + tint = colors.White, + ) + Text( + text = stringResource(R.string.group_note_info), + modifier = Modifier.padding(start = 8.dp), + color = colors.Grey01, + style = typography.info_r400_s12 + ) + } + } + items(filteredItems) { item -> + when (item) { + is GroupNoteRecord -> TextCommentCard(data = item) + is GroupNoteVote -> VoteCommentCard(data = item) + } + } + } + } + } + FloatingButton( + icon = painterResource(id = R.drawable.ic_plus), + onClick = { /* 새 글 작성 */ } + ) +} + +@Preview +@Composable +private fun GroupNoteScreenPreview() { + ThipTheme { + GroupNoteScreen() + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_information.xml b/app/src/main/res/drawable/ic_information.xml new file mode 100644 index 00000000..15fd3ffd --- /dev/null +++ b/app/src/main/res/drawable/ic_information.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d3b28e70..0448d904 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -166,4 +166,5 @@ 내 기록 페이지별 보기 총평 보기 + 내 진행도에 따라 일부 댓글은 블러처리됩니다. \ No newline at end of file From b3bc9a081d7bb2eb85f926500867d78ce20e6727 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 15:34:26 +0900 Subject: [PATCH 07/50] =?UTF-8?q?[ui]:=20=EC=A7=84=ED=96=89=EB=8F=84=20?= =?UTF-8?q?=EB=B8=94=EB=9F=AC=ED=9A=A8=EA=B3=BC=20=EC=B6=94=EA=B0=80=20(#3?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/group/note/component/TextCommentCard.kt | 6 ++++++ .../thip/ui/group/note/component/VoteCommentCard.kt | 10 +++++++++- .../com/texthip/thip/ui/group/note/mock/CommentData.kt | 7 +++++++ .../thip/ui/group/note/screen/GroupNoteScreen.kt | 9 ++++----- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt index 34cf24f8..ee3dd70e 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.blur import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -23,11 +24,15 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun TextCommentCard( + modifier: Modifier = Modifier, data: GroupNoteRecord, ) { var isLiked by remember { mutableStateOf(data.isLiked) } Column( + modifier = modifier + .blur(if (data.isLocked) 5.dp else 0.dp) + .padding(vertical = 16.dp, horizontal = 20.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { ProfileBar( @@ -75,6 +80,7 @@ fun TextCommentCardPreview() { commentCount = 123, isLiked = true, isWriter = false, + isLocked = false, recordId = 1 ) ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt index 719d1e23..5d7b0030 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt @@ -2,12 +2,15 @@ package com.texthip.thip.ui.group.note.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding 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.draw.blur import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -23,6 +26,7 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun VoteCommentCard( + modifier: Modifier = Modifier, data: GroupNoteVote, ) { var isLiked by remember { mutableStateOf(data.isLiked) } @@ -31,6 +35,9 @@ fun VoteCommentCard( val hasVoted = voteItems.any { it.isVoted } Column( + modifier = modifier + .blur(if (data.isLocked) 5.dp else 0.dp) + .padding(vertical = 16.dp, horizontal = 20.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { ProfileBar( @@ -78,7 +85,7 @@ fun VoteCommentCard( onLikeClick = { isLiked = !isLiked }, - onCommentClick = { }, + onCommentClick = { }, ) } } @@ -98,6 +105,7 @@ private fun VoteCommentCardPreview() { commentCount = 123, isLiked = true, isWriter = false, + isLocked = false, voteId = 1, voteItems = listOf( VoteItem(1, "김땡땡", 90, false), diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt b/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt index 668216cf..6885b63b 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/mock/CommentData.kt @@ -12,6 +12,7 @@ sealed class GroupNoteItem { abstract val commentCount: Int abstract val isLiked: Boolean abstract val isWriter: Boolean + abstract val isLocked: Boolean } data class GroupNoteRecord( @@ -25,6 +26,7 @@ data class GroupNoteRecord( override val commentCount: Int, override val isLiked: Boolean, override val isWriter: Boolean, + override val isLocked: Boolean, val recordId: Int ) : GroupNoteItem() @@ -40,6 +42,7 @@ data class GroupNoteVote( override val isLiked: Boolean, override val isWriter: Boolean, val voteId: Int, + override val isLocked: Boolean, val voteItems: List ) : GroupNoteItem() @@ -62,6 +65,7 @@ val mockGroupNoteItems: List = listOf( commentCount = 123, isLiked = true, isWriter = false, + isLocked = false, recordId = 1 ), GroupNoteVote( @@ -75,6 +79,7 @@ val mockGroupNoteItems: List = listOf( commentCount = 123, isLiked = false, isWriter = false, + isLocked = true, voteId = 1, voteItems = listOf( VoteItem(1, "김땡땡", 90, false), @@ -92,6 +97,7 @@ val mockGroupNoteItems: List = listOf( commentCount = 123, isLiked = false, isWriter = true, + isLocked = false, recordId = 1 ), GroupNoteVote( @@ -105,6 +111,7 @@ val mockGroupNoteItems: List = listOf( commentCount = 123, isLiked = true, isWriter = true, + isLocked = false, voteId = 1, voteItems = listOf( VoteItem(1, "김땡땡", 90, false), diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt index 4e57c8ff..1b546b16 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt @@ -9,8 +9,8 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.Icon -import androidx.compose.material.Text +import androidx.compose.material3.Icon +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -102,12 +102,11 @@ fun GroupNoteScreen() { LazyColumn( modifier = Modifier .fillMaxSize() - .padding(bottom = 82.dp) - .padding(20.dp), - verticalArrangement = Arrangement.spacedBy(32.dp) + .padding(bottom = 82.dp), ) { item{ Row( + modifier = Modifier.padding(start = 20.dp, end = 20.dp, bottom = 16.dp, top = 20.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp), ) { From 0273fbf09b85496e7878707cf7a8beee86e4b380 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 16:51:48 +0900 Subject: [PATCH 08/50] =?UTF-8?q?[refactor]:=20=ED=95=84=ED=84=B0=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EB=88=8C=EB=A0=80=EC=9D=84=20=EB=95=8C=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EA=B3=A0=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/buttons/FilterButton.kt | 71 +++++----- .../ui/group/note/screen/GroupNoteScreen.kt | 130 +++++++++--------- 2 files changed, 102 insertions(+), 99 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt index bb5e1710..a0c3b27a 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row 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.width @@ -42,15 +43,18 @@ fun FilterButton( ) { var expanded by remember { mutableStateOf(false) } - Column( - modifier = modifier.fillMaxWidth(), - horizontalAlignment = Alignment.End + Box( + modifier = modifier + .fillMaxWidth(), + contentAlignment = Alignment.TopEnd ) { + // 버튼 영역 Row( modifier = Modifier + .height(36.dp) .clickable( interactionSource = remember { MutableInteractionSource() }, - indication = null // 클릭 효과 제거 + indication = null ) { expanded = !expanded }, horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically @@ -68,46 +72,41 @@ fun FilterButton( tint = colors.Grey02, modifier = Modifier.size(24.dp) ) - } - // 드롭다운 애니메이션 박스 + // 드롭다운 AnimatedVisibility( visible = expanded, enter = fadeIn(), exit = fadeOut() ) { - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.TopEnd + Column( + modifier = Modifier + .padding(top = 36.dp) // 버튼 아래로 띄우기 + .width(144.dp) + .border( + width = 1.dp, + color = colors.Grey01, + shape = RoundedCornerShape(16.dp) + ) + .background(color = colors.Black, shape = RoundedCornerShape(16.dp)) + .padding(vertical = 20.dp, horizontal = 12.dp) + .align(Alignment.TopEnd), // 오버레이 위치 고정 + verticalArrangement = Arrangement.spacedBy(16.dp) ) { - Column( - modifier = Modifier - .padding(top = 8.dp) - .width(144.dp) - .border( - width = 1.dp, - color = colors.Grey01, - shape = RoundedCornerShape(16.dp) - ) - .background(color = colors.Black, shape = RoundedCornerShape(16.dp)) - .padding(vertical = 20.dp, horizontal = 12.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - options.forEach { option -> - val isSelected = option == selectedOption - Text( - text = option, - color = if (isSelected) colors.White else colors.Grey02, - style = typography.feedcopy_r400_s14_h20, - modifier = Modifier - .fillMaxWidth() - .clickable { - onOptionSelected(option) - expanded = false - } - ) - } + options.forEach { option -> + val isSelected = option == selectedOption + Text( + text = option, + color = if (isSelected) colors.White else colors.Grey02, + style = typography.feedcopy_r400_s14_h20, + modifier = Modifier + .fillMaxWidth() + .clickable { + onOptionSelected(option) + expanded = false + } + ) } } } diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt index 1b546b16..c6571eb2 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt @@ -63,75 +63,79 @@ fun GroupNoteScreen() { onLeftClick = {} ) - Column { - HeaderMenuBarTab( - titles = tabs, - selectedTabIndex = selectedTabIndex, - onTabSelected = { selectedTabIndex = it }, - modifier = Modifier - .fillMaxWidth() - .padding(top = 20.dp) - ) - - Box( - modifier = Modifier - .fillMaxWidth() - .padding(top = 20.dp), - contentAlignment = Alignment.CenterStart - ) { - FilterButton( - modifier = Modifier - .fillMaxWidth() - .padding(end = 20.dp), - selectedOption = selectedFilter, - options = filters, - onOptionSelected = { selectedFilter = it } - ) - FilterHeaderSection( - firstPage = firstPage, - lastPage = lastPage, - isTotalSelected = isTotalSelected, - totalEnabled = totalEnabled, - onFirstPageChange = { firstPage = it }, - onLastPageChange = { lastPage = it }, - onTotalToggle = { isTotalSelected = !isTotalSelected }, - ) - } + HeaderMenuBarTab( + titles = tabs, + selectedTabIndex = selectedTabIndex, + onTabSelected = { selectedTabIndex = it }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp, bottom = 56.dp) + ) - // 피드 리스트 영역 - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(bottom = 82.dp), - ) { - item{ - Row( - modifier = Modifier.padding(start = 20.dp, end = 20.dp, bottom = 16.dp, top = 20.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - Icon( - painterResource(R.drawable.ic_information), - contentDescription = null, - tint = colors.White, - ) - Text( - text = stringResource(R.string.group_note_info), - modifier = Modifier.padding(start = 8.dp), - color = colors.Grey01, - style = typography.info_r400_s12 - ) - } + // 피드 리스트 영역 + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 82.dp), + ) { + item { + Row( + modifier = Modifier.padding( + start = 20.dp, + end = 20.dp, + bottom = 16.dp, + top = 20.dp + ), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + Icon( + painterResource(R.drawable.ic_information), + contentDescription = null, + tint = colors.White, + ) + Text( + text = stringResource(R.string.group_note_info), + modifier = Modifier.padding(start = 8.dp), + color = colors.Grey01, + style = typography.info_r400_s12 + ) } - items(filteredItems) { item -> - when (item) { - is GroupNoteRecord -> TextCommentCard(data = item) - is GroupNoteVote -> VoteCommentCard(data = item) - } + } + items(filteredItems) { item -> + when (item) { + is GroupNoteRecord -> TextCommentCard(data = item) + is GroupNoteVote -> VoteCommentCard(data = item) } } } } + + Box( + modifier = Modifier + .fillMaxWidth() + .padding(top = 136.dp), + ) { + FilterHeaderSection( + firstPage = firstPage, + lastPage = lastPage, + isTotalSelected = isTotalSelected, + totalEnabled = totalEnabled, + onFirstPageChange = { firstPage = it }, + onLastPageChange = { lastPage = it }, + onTotalToggle = { isTotalSelected = !isTotalSelected }, + ) + + FilterButton( + modifier = Modifier + .align(Alignment.CenterEnd) + .padding(end = 20.dp), + selectedOption = selectedFilter, + options = filters, + onOptionSelected = { selectedFilter = it } + ) + } + FloatingButton( icon = painterResource(id = R.drawable.ic_plus), onClick = { /* 새 글 작성 */ } From 976ceece9122c27f3279e152d7d84875779193ea Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Tue, 8 Jul 2025 16:53:37 +0900 Subject: [PATCH 09/50] =?UTF-8?q?[refactor]:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=ED=95=84=ED=84=B0=20zindex=20=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/group/note/screen/GroupNoteScreen.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt index c6571eb2..2c986a8f 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteScreen.kt @@ -116,6 +116,15 @@ fun GroupNoteScreen() { .fillMaxWidth() .padding(top = 136.dp), ) { + FilterButton( + modifier = Modifier + .align(Alignment.CenterEnd) + .padding(end = 20.dp), + selectedOption = selectedFilter, + options = filters, + onOptionSelected = { selectedFilter = it } + ) + FilterHeaderSection( firstPage = firstPage, lastPage = lastPage, @@ -125,15 +134,6 @@ fun GroupNoteScreen() { onLastPageChange = { lastPage = it }, onTotalToggle = { isTotalSelected = !isTotalSelected }, ) - - FilterButton( - modifier = Modifier - .align(Alignment.CenterEnd) - .padding(end = 20.dp), - selectedOption = selectedFilter, - options = filters, - onOptionSelected = { selectedFilter = it } - ) } FloatingButton( From 4ca99fb044380fb169aab65e45e61342ddf84a67 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:52:07 +0900 Subject: [PATCH 10/50] =?UTF-8?q?[chore]:=20misc=20gitignore=EC=97=90=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 64ef9d56..bbc1ecb0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ .externalNativeBuild .cxx local.properties -.idea/deploymentTargetSelector.xml \ No newline at end of file +.idea/deploymentTargetSelector.xml +.idea/misc.xml \ No newline at end of file From fa4fae85e57881decfc3a5c6c10c055abf08546f Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:52:44 +0900 Subject: [PATCH 11/50] =?UTF-8?q?[ui]:=20profile=20bar=20feed=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EC=9E=91=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/header/ProfileBarFeed.kt | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt new file mode 100644 index 00000000..b74bb4d2 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt @@ -0,0 +1,95 @@ +package com.texthip.thip.ui.common.header + +import androidx.compose.foundation.Image +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.height +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun ProfileBarFeed( + profileImage: Painter?, + nickname: String, + genreName: String, + genreColor: Color = colors.NeonGreen, + date: String, +) { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Row { + if (profileImage != null) { + Image( + painter = profileImage, + contentDescription = "프로필 이미지", + modifier = Modifier + .size(24.dp) + .clip(CircleShape) + ) + } else { + Box( + modifier = Modifier + .size(24.dp) + .clip(CircleShape) + .background(colors.Grey) + ) + } + Spacer(modifier = Modifier.width(4.dp)) + Column { + Text( + text = nickname, + style = typography.menu_sb600_s12, + color = colors.White + ) + Spacer(modifier = Modifier.height(2.dp)) + Text( + text = genreName, + style = typography.timedate_r400_s11, + color = genreColor + ) + } + } + + Text( + text = date, + style = typography.timedate_r400_s11, + color = colors.Grey01 + ) + } +} + +@Preview(showBackground = true) +@Composable +fun ProfileBarFeedPreview() { + ThipTheme { + ProfileBarFeed( + profileImage = null, + nickname = "user.01", + genreName = "칭호칭호", + genreColor = colors.Orange, + date = "2025.01.12" + ) + } +} \ No newline at end of file From b1895f2fe705646d01a7fb0be81ce333f136ab3d Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:43:18 +0900 Subject: [PATCH 12/50] =?UTF-8?q?[ui]:=20comment=20item=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EC=9E=91=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/group/note/component/CommentItem.kt | 148 ++++++++++++++++++ .../thip/ui/group/note/mock/ReplyData.kt | 80 ++++++++++ app/src/main/res/drawable/ic_heart_center.xml | 13 ++ .../res/drawable/ic_heart_center_filled.xml | 9 ++ 4 files changed, 250 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/mock/ReplyData.kt create mode 100644 app/src/main/res/drawable/ic_heart_center.xml create mode 100644 app/src/main/res/drawable/ic_heart_center_filled.xml diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt new file mode 100644 index 00000000..6672518a --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt @@ -0,0 +1,148 @@ +package com.texthip.thip.ui.group.note.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +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.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.header.ProfileBarFeed +import com.texthip.thip.ui.group.note.mock.CommentItem +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun CommentItem( + modifier: Modifier = Modifier, + data: CommentItem, + onReplyClick: (String) -> Unit = { } +) { + var isLiked by remember { mutableStateOf(data.isLiked) } + + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + ProfileBarFeed( +// profileImage = data.profileImageUrl, + profileImage = painterResource(R.drawable.character_literature), + nickname = data.nickName, + genreName = data.genreName, + genreColor = colors.Orange, + date = data.postDate + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(20.dp) + ) { + Column( + modifier = Modifier + .weight(1f), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = data.content, + color = colors.Grey, + style = typography.feedcopy_r400_s14_h20, + ) + Text( + modifier = Modifier.clickable(onClick = { onReplyClick(data.nickName) }), + text = stringResource(R.string.write_reply), + style = typography.menu_sb600_s12, + color = colors.Grey02, + ) + } + + Column( + modifier = Modifier.clickable(onClick = { isLiked = !isLiked }), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { + Icon( + painter = painterResource(if (isLiked) R.drawable.ic_heart_center_filled else R.drawable.ic_heart_center), + contentDescription = null, + tint = Color.Unspecified + ) + Text( + text = data.likeCount.toString(), + style = typography.navi_m500_s10, + color = colors.White, + ) + } + } + } +} + + +@Preview +@Composable +private fun CommentItemPreview() { + ThipTheme { + Column( + modifier = Modifier + .clickable { /* TODO: Handle click */ } + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + CommentItem( + data = CommentItem( + commentId = 1, + userId = 1, + nickName = "user.01", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile.jpg", + content = "입력하세요. 댓글 내용을 입력하세요오. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. ", + postDate = "2025.01.12", + isWriter = false, + isLiked = true, + likeCount = 10, + ) + ) + + CommentItem( + data = CommentItem( + commentId = 1, + userId = 1, + nickName = "user.01", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile.jpg", + content = "입력하세요. 댓글 내용을 입력하세요오. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요.", + postDate = "12시간 전", + isWriter = false, + isLiked = true, + likeCount = 10 + ) + ) + + CommentItem( + data = CommentItem( + commentId = 1, + userId = 1, + nickName = "user.01", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile.jpg", + content = "입력하세요.", + postDate = "12시간 전", + isWriter = false, + isLiked = true, + likeCount = 10 + ) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/mock/ReplyData.kt b/app/src/main/java/com/texthip/thip/ui/group/note/mock/ReplyData.kt new file mode 100644 index 00000000..f48e99d3 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/mock/ReplyData.kt @@ -0,0 +1,80 @@ +package com.texthip.thip.ui.group.note.mock + +data class CommentItem( + val commentId: Int, + val userId: Int, + val nickName: String, + val genreName: String, + val profileImageUrl: String, + val content: String, + val postDate: String, + val isWriter: Boolean, + val isLiked: Boolean, + val likeCount: Int, + val replyList: List = emptyList() +) + +data class ReplyItem( + val replyId: Int, + val userId: Int, + val nickName: String, + val genreName: String, + val profileImageUrl: String, + val parentNickname: String, + val content: String, + val postDate: String, + val isWriter: Boolean, + val isLiked: Boolean, + val likeCount: Int +) + +data class CommentResponse( + val commentList: List +) + +val mockComment = CommentItem( + commentId = 1, + userId = 1, + nickName = "user.01", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile.jpg", + content = "입력하세요. 댓글 내용을 입력하세요오. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. ", + postDate = "2025.01.12", + isWriter = false, + isLiked = true, + likeCount = 123, + replyList = listOf( + ReplyItem( + replyId = 1, + userId = 2, + nickName = "user.02", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile2.jpg", + parentNickname = "user.01", + content = "답글 내용입니다.", + postDate = "12시간 전", + isWriter = false, + isLiked = false, + likeCount = 123 + ), + ReplyItem( + replyId = 1, + userId = 2, + nickName = "user.02", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile2.jpg", + parentNickname = "user.01", + content = "답글 내용입니다.", + postDate = "2025.01.13", + isWriter = false, + isLiked = false, + likeCount = 2 + ) + ) +) + +val mockCommentList = CommentResponse( + commentList = listOf( + mockComment, mockComment + ) +) diff --git a/app/src/main/res/drawable/ic_heart_center.xml b/app/src/main/res/drawable/ic_heart_center.xml new file mode 100644 index 00000000..ed8d7c47 --- /dev/null +++ b/app/src/main/res/drawable/ic_heart_center.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/ic_heart_center_filled.xml b/app/src/main/res/drawable/ic_heart_center_filled.xml new file mode 100644 index 00000000..6cad574d --- /dev/null +++ b/app/src/main/res/drawable/ic_heart_center_filled.xml @@ -0,0 +1,9 @@ + + + From 3ea1cc472502d59c74a383662efdf6913a219f8e Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:43:30 +0900 Subject: [PATCH 13/50] =?UTF-8?q?[ui]:=20reply=20item=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EC=9E=91=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/group/note/component/ReplyItem.kt | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt new file mode 100644 index 00000000..16353fee --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt @@ -0,0 +1,139 @@ +package com.texthip.thip.ui.group.note.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +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.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.header.ProfileBarFeed +import com.texthip.thip.ui.group.note.mock.ReplyItem +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun ReplyItem( + modifier: Modifier = Modifier, + data: ReplyItem, + onReplyClick: (String) -> Unit = { } +) { + var isLiked by remember { mutableStateOf(data.isLiked) } + + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + painter = painterResource(R.drawable.ic_reply), + contentDescription = null, + tint = Color.White + ) + + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + ProfileBarFeed( +// profileImage = data.profileImageUrl, + profileImage = painterResource(R.drawable.character_literature), + nickname = data.nickName, + genreName = data.genreName, + genreColor = colors.Orange, + date = data.postDate + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(20.dp) + ) { + Column( + modifier = Modifier + .weight(1f), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = buildAnnotatedString { + withStyle( + style = typography.copy_m500_s14_h20.copy(color = colors.White) + .toSpanStyle() + ) { + append(stringResource(R.string.annotation) + data.parentNickname + stringResource(R.string.space_bar)) + } + append(data.content) + }, + color = colors.Grey, + style = typography.feedcopy_r400_s14_h20, + ) + Text( + modifier = Modifier.clickable(onClick = { onReplyClick(data.nickName) }), + text = stringResource(R.string.write_reply), + style = typography.menu_sb600_s12, + color = colors.Grey02, + ) + } + + Column( + modifier = Modifier.clickable(onClick = { isLiked = !isLiked }), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { + Icon( + painter = painterResource(if (isLiked) R.drawable.ic_heart_center_filled else R.drawable.ic_heart_center), + contentDescription = null, + tint = Color.Unspecified + ) + Text( + text = data.likeCount.toString(), + style = typography.navi_m500_s10, + color = colors.White, + ) + } + } + } + } + +} + +@Preview +@Composable +private fun ReplyItemPreview() { + ThipTheme { + Column( + modifier = Modifier + .clickable { /* TODO: Handle click */ } + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + ReplyItem( + data = ReplyItem( + replyId = 1, + userId = 1, + nickName = "user.01", + parentNickname = "사용자태그", + genreName = "칭호칭호", + profileImageUrl = "https://example.com/profile.jpg", + content = "입력하세요. 댓글 내용을 입력하세요오. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. 댓글 내용을 입력하세요. ", + postDate = "12시간 전", + isWriter = false, + isLiked = true, + likeCount = 10, + ) + ) + } + } +} \ No newline at end of file From 97707fe289ffece66bf5671d6806d2e26c6f269d Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:43:39 +0900 Subject: [PATCH 14/50] =?UTF-8?q?[ui]:=20comment=20section=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EC=9E=91=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/group/note/component/CommentSection.kt | 105 ++++++++++++++++++ app/src/main/res/values/strings.xml | 4 + 2 files changed, 109 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt new file mode 100644 index 00000000..a38d4617 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentSection.kt @@ -0,0 +1,105 @@ +package com.texthip.thip.ui.group.note.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +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.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.forms.CommentTextField +import com.texthip.thip.ui.group.note.mock.CommentItem +import com.texthip.thip.ui.group.note.mock.ReplyItem +import com.texthip.thip.ui.group.note.mock.mockComment +import com.texthip.thip.ui.theme.ThipTheme + +@Composable +fun CommentSection( + commentItem: CommentItem, + onSendReply: (String, Int?, String?) -> Unit +) { + val scrollState = rememberScrollState() + + var inputText by remember { mutableStateOf("") } + var replyingTo by remember { mutableStateOf(null) } + + Box { + Column( + modifier = Modifier + .fillMaxHeight() + .padding(horizontal = 20.dp) + .verticalScroll(scrollState), + verticalArrangement = Arrangement.spacedBy(20.dp), + horizontalAlignment = Alignment.Start + ) { + CommentItem( + data = commentItem, + onReplyClick = { + replyingTo = ReplyItem( + replyId = -1, + userId = commentItem.userId, + nickName = commentItem.nickName, + parentNickname = "", + genreName = commentItem.genreName, + profileImageUrl = commentItem.profileImageUrl, + content = commentItem.content, + postDate = commentItem.postDate, + isWriter = commentItem.isWriter, + isLiked = commentItem.isLiked, + likeCount = commentItem.likeCount + ) + } + ) + + commentItem.replyList.forEach { reply -> + ReplyItem( + data = reply, + onReplyClick = { replyingTo = reply } + ) + } + } + + CommentTextField( + modifier = Modifier + .align(Alignment.BottomCenter), + hint = stringResource(R.string.reply_to), + input = inputText, + onInputChange = { inputText = it }, + onSendClick = { + onSendReply( + inputText, + replyingTo?.replyId, + replyingTo?.nickName + ) + inputText = "" + replyingTo = null + }, + replyTo = replyingTo?.nickName, + onCancelReply = { replyingTo = null } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun CommentSectionPreview() { + ThipTheme { + CommentSection( + commentItem = mockComment, + onSendReply = { text, replyId, parentNickname -> + println("전송됨: '$text' → replyId: $replyId, to: @$parentNickname") + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0448d904..b4028e66 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -167,4 +167,8 @@ 페이지별 보기 총평 보기 내 진행도에 따라 일부 댓글은 블러처리됩니다. + 답글작성 + \@ + \ + 00님에게 댓글을 남겨보세요. \ No newline at end of file From 89c360d3c3045ca32d906467bd58be06b3b5a300 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:46:10 +0900 Subject: [PATCH 15/50] =?UTF-8?q?[refactor]:=20bottom=20sheet=20data=20cla?= =?UTF-8?q?ss=20=EB=B6=84=EB=A6=AC=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/bottomsheet/MenuBottomSheet.kt | 8 +------- .../thip/ui/group/room/mock/MenuBottomSheetItem.kt | 10 ++++++++++ .../thip/ui/group/room/screen/GroupRoomScreen.kt | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/room/mock/MenuBottomSheetItem.kt diff --git a/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt b/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt index e4e5d71c..750025fe 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt @@ -28,23 +28,17 @@ import androidx.compose.runtime.rememberCoroutineScope 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.input.pointer.pointerInput import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import com.texthip.thip.R +import com.texthip.thip.ui.group.room.mock.MenuBottomSheetItem import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography import kotlinx.coroutines.launch -data class MenuBottomSheetItem( - val text: String, - val color: Color = Color.White, - val onClick: () -> Unit, -) - @Composable fun MenuBottomSheet( items: List, diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/MenuBottomSheetItem.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/MenuBottomSheetItem.kt new file mode 100644 index 00000000..59c61c41 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/room/mock/MenuBottomSheetItem.kt @@ -0,0 +1,10 @@ +package com.texthip.thip.ui.group.room.mock + +import androidx.compose.ui.graphics.Color + +data class MenuBottomSheetItem( + val text: String, + val color: Color = Color.White, + val onClick: () -> Unit, +) + diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt index 36c5d66b..92521fdd 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt @@ -25,12 +25,12 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.bottomsheet.MenuBottomSheet -import com.texthip.thip.ui.common.bottomsheet.MenuBottomSheetItem import com.texthip.thip.ui.common.topappbar.GradationTopAppBar import com.texthip.thip.ui.group.room.component.GroupRoomBody import com.texthip.thip.ui.group.room.component.GroupRoomHeader import com.texthip.thip.ui.group.room.mock.GroupRoomBodyData import com.texthip.thip.ui.group.room.mock.GroupRoomHeaderData +import com.texthip.thip.ui.group.room.mock.MenuBottomSheetItem import com.texthip.thip.ui.group.room.mock.mockVoteData import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors From b7fb973ded499d2608461abe040fea267d988fe8 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:49:38 +0900 Subject: [PATCH 16/50] =?UTF-8?q?[refactor]:=20page=20text=20field?= =?UTF-8?q?=EC=97=90=20=EC=88=AB=EC=9E=90=EB=A7=8C=20=EC=9E=85=EB=A0=A5=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/common/forms/PageTextField.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/PageTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/PageTextField.kt index f2806710..4c5bd43a 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/PageTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/PageTextField.kt @@ -36,12 +36,18 @@ fun PageTextField( ) { BasicTextField( value = text, - onValueChange = onTextChange, + onValueChange = { newText -> + // 숫자만 필터링 + if (newText.all { it.isDigit() }) { + onTextChange(newText) + } + }, textStyle = typography.copy_r400_s14.copy(color = colors.White), keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Number ), cursorBrush = SolidColor(colors.NeonGreen), + maxLines = 1, ) } } From fd7e5c59588c89179c4ba8a9c6e46e45672a3aaa Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 01:09:42 +0900 Subject: [PATCH 17/50] =?UTF-8?q?[refactor]:=20=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EB=B0=94=EA=B9=A5=20=EC=98=81=EC=97=AD=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AC=ED=96=88=EC=9D=84=20=EB=95=8C=20=EB=93=9C?= =?UTF-8?q?=EB=A1=AD=EB=8B=A4=EC=9A=B4=20=EB=8B=AB=ED=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/common/buttons/FilterButton.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt index a0c3b27a..f717013e 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/FilterButton.kt @@ -48,6 +48,20 @@ fun FilterButton( .fillMaxWidth(), contentAlignment = Alignment.TopEnd ) { + // 바깥 클릭 감지(expanded 상태에서만 보이도록 함) + if (expanded) { + Box( + modifier = Modifier + .fillMaxSize() + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null + ) { + expanded = false + } + ) + } + // 버튼 영역 Row( modifier = Modifier From 39c0e60d1a9f56505618142d9d56ecbcd24f36d0 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 01:10:30 +0900 Subject: [PATCH 18/50] =?UTF-8?q?[chore]:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=A3=BC=EC=84=9D=20=EC=82=AD=EC=A0=9C=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/group/note/component/VoteCommentCard.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt index 5d7b0030..a31b57c2 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt @@ -47,7 +47,6 @@ fun VoteCommentCard( bottomText = data.page.toString() + stringResource(R.string.page), bottomTextColor = colors.Purple, showSubscriberInfo = false, -// hoursAgo = data.postDate hoursAgo = data.postDate ) From 8cc24711667bd94b7d6918a916412f05df939859 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 01:14:51 +0900 Subject: [PATCH 19/50] =?UTF-8?q?[refactor]:=20=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20=EA=B0=92=EB=93=A4=20=EC=83=81=EC=88=98=ED=99=94?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20(#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/common/bottomsheet/MenuBottomSheet.kt | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt b/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt index 750025fe..f5aa5d53 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt @@ -39,21 +39,26 @@ import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography import kotlinx.coroutines.launch +private const val BOTTOM_SHEET_HIDDEN_OFFSET = 300f +private const val BOTTOM_SHEET_VISIBLE_OFFSET = 0f +private const val BOTTOM_SHEET_DISMISS_THRESHOLD = 100f +private const val ANIMATION_DURATION = 300 + @Composable fun MenuBottomSheet( items: List, onDismiss: () -> Unit ) { val scope = rememberCoroutineScope() - val animatableOffset = remember { Animatable(300f) } // 시작 위치 아래 - var offsetY by remember { mutableFloatStateOf(0f) } + val animatableOffset = remember { Animatable(BOTTOM_SHEET_HIDDEN_OFFSET) } // 시작 위치 아래 + var offsetY by remember { mutableFloatStateOf(BOTTOM_SHEET_VISIBLE_OFFSET) } var isDismissing by remember { mutableStateOf(false) } // 등장 애니메이션 LaunchedEffect(Unit) { animatableOffset.animateTo( - targetValue = 0f, - animationSpec = tween(durationMillis = 300) + targetValue = BOTTOM_SHEET_VISIBLE_OFFSET, + animationSpec = tween(durationMillis = ANIMATION_DURATION) ) } @@ -68,7 +73,10 @@ fun MenuBottomSheet( if (!isDismissing) { isDismissing = true scope.launch { - animatableOffset.animateTo(300f, tween(300)) + animatableOffset.animateTo( + BOTTOM_SHEET_HIDDEN_OFFSET, + tween(ANIMATION_DURATION) + ) onDismiss() } } @@ -101,14 +109,17 @@ fun MenuBottomSheet( } }, onDragEnd = { - if (offsetY > 100f && !isDismissing) { + if (offsetY > BOTTOM_SHEET_DISMISS_THRESHOLD && !isDismissing) { isDismissing = true scope.launch { - animatableOffset.animateTo(300f, tween(300)) + animatableOffset.animateTo( + BOTTOM_SHEET_HIDDEN_OFFSET, + tween(ANIMATION_DURATION) + ) onDismiss() } } else { - offsetY = 0f + offsetY = BOTTOM_SHEET_VISIBLE_OFFSET } } ) From a7f305e631279f6d02cfc2220a6b556b8cef588a Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:08:08 +0900 Subject: [PATCH 20/50] =?UTF-8?q?[ui]:=20=EA=B8=B0=EC=A1=B4=EC=9D=98=20?= =?UTF-8?q?=EC=95=8C=EB=9E=8C=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#36)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Conflicts: # app/src/main/res/values/strings.xml --- .../com/texthip/thip/ui/common/cards/CardAlarm.kt | 12 +++++++----- app/src/main/res/values/strings.xml | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt index e23d86a6..16dd30ad 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt @@ -9,6 +9,7 @@ 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.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -86,11 +87,12 @@ fun CardAlarm( ) } - Spacer(modifier = Modifier.width(12.dp)) + Spacer(modifier = Modifier.width(8.dp)) // 내용 (제목, 빨간 점, 시간, 메시지) Column( - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.Center ) { Row( modifier = Modifier.fillMaxWidth(), @@ -98,7 +100,7 @@ fun CardAlarm( ) { Text( text = title, - style = typography.menu_sb600_s14_h24, + style = typography.view_m500_s14, color = if (isRead) colors.Grey01 else colors.White, modifier = Modifier.weight(1f), maxLines = 1, @@ -121,7 +123,7 @@ fun CardAlarm( Text( text = timeAgo + stringResource(R.string.time_ago), - style = typography.view_m500_s12_h20, + style = typography.timedate_r400_s11, color = if (isRead) colors.Grey02 else colors.Grey01, ) } @@ -129,7 +131,7 @@ fun CardAlarm( } } - Spacer(modifier = Modifier.width(12.dp)) + Spacer(modifier = Modifier.height(12.dp)) Text( text = message, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b4028e66..93908491 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -166,6 +166,11 @@ 내 기록 페이지별 보기 총평 보기 + + + 피드 + 모임 + 알림 내 진행도에 따라 일부 댓글은 블러처리됩니다. 답글작성 \@ From 3eba2b49124c10b59e09f488eb3017da51b2a2a1 Mon Sep 17 00:00:00 2001 From: Gyubin Date: Tue, 8 Jul 2025 13:01:01 +0900 Subject: [PATCH 21/50] =?UTF-8?q?[ui]:=20=EC=95=8C=EB=9E=8C=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=B6=94=EA=B0=80=20(#36)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../alarmpage/component/AlarmFilterRow.kt | 49 +++++++++++++++++++ .../ui/common/alarmpage/mock/AlarmItem.kt | 10 ++++ app/src/main/res/drawable/ic_notification.xml | 9 ++++ 3 files changed, 68 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/AlarmFilterRow.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/common/alarmpage/mock/AlarmItem.kt create mode 100644 app/src/main/res/drawable/ic_notification.xml diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/AlarmFilterRow.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/AlarmFilterRow.kt new file mode 100644 index 00000000..f70659bc --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/AlarmFilterRow.kt @@ -0,0 +1,49 @@ +package com.texthip.thip.ui.common.alarmpage.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +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.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.buttons.OptionChipButton + +@Composable +fun AlarmFilterRow( + selectedStates: BooleanArray, + onToggle: (Int) -> Unit +) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + OptionChipButton( + text = stringResource(R.string.alarm_feed), + isFilled = true, + onClick = { onToggle(0) } + ) + OptionChipButton( + text = stringResource(R.string.alarm_group), + isFilled = true, + onClick = { onToggle(1) } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun AlarmFilterRowPreview() { + var selectedStates by remember { mutableStateOf(booleanArrayOf(false, false)) } + + AlarmFilterRow( + selectedStates = selectedStates, + onToggle = { idx -> + selectedStates = selectedStates.copyOf().also { it[idx] = !it[idx] } + } + ) +} + diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/mock/AlarmItem.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/mock/AlarmItem.kt new file mode 100644 index 00000000..84bc094f --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/mock/AlarmItem.kt @@ -0,0 +1,10 @@ +package com.texthip.thip.ui.common.alarmpage.mock + +data class AlarmItem( + val id: Int, + val badgeText: String, + val title: String, + val message: String, + val timeAgo: String, + var isRead: Boolean +) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_notification.xml b/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 00000000..42aaeff8 --- /dev/null +++ b/app/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,9 @@ + + + From a61416b9bc99c5c48ef4387f2189bd77f22e116a Mon Sep 17 00:00:00 2001 From: Gyubin Date: Tue, 8 Jul 2025 13:02:08 +0900 Subject: [PATCH 22/50] =?UTF-8?q?[ui]:=20=EC=95=8C=EB=9E=8C=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4(=EA=B3=B5=ED=86=B5)=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=20(#36)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/common/alarmpage/screen/AlarmScreen.kt | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt new file mode 100644 index 00000000..e75881ef --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt @@ -0,0 +1,145 @@ +package com.texthip.thip.ui.common.alarmpage.screen + +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.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +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.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.texthip.thip.R +import com.texthip.thip.ui.common.alarmpage.component.AlarmFilterRow +import com.texthip.thip.ui.common.alarmpage.mock.AlarmItem +import com.texthip.thip.ui.common.cards.CardAlarm +import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.theme.ThipTheme +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun AlarmScreen( + alarmItems: List, onCardClick: (AlarmItem) -> Unit = {} +) { + var selectedStates by remember { mutableStateOf(booleanArrayOf(false, false)) } + var alarms by remember { mutableStateOf(alarmItems) } + + val filteredList = when { + selectedStates[0] && !selectedStates[1] -> alarms.filter { it.badgeText == stringResource(R.string.alarm_feed) } + !selectedStates[0] && selectedStates[1] -> alarms.filter { it.badgeText == stringResource(R.string.alarm_group) } + selectedStates[0] && selectedStates[1] -> alarms + else -> alarms + } + + Column( + Modifier + .background(colors.Black) + .fillMaxSize() + ) { + DefaultTopAppBar( + title = stringResource(R.string.alarm_string), + onLeftClick = {}, + ) + Column( + Modifier + .background(colors.Black) + .fillMaxSize() + .padding(horizontal = 20.dp) + ) { + Spacer(modifier = Modifier.height(20.dp)) + AlarmFilterRow( + selectedStates = selectedStates, onToggle = { idx -> + selectedStates = selectedStates.copyOf().also { it[idx] = !it[idx] } + }) + Spacer(modifier = Modifier.height(20.dp)) + + if (filteredList.isEmpty()) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Icon( + painter = painterResource(R.drawable.ic_notification), + contentDescription = null, + tint = colors.Grey02, + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = stringResource(R.string.alarm_notification_comment), + style = typography.smalltitle_sb600_s16_h20, + color = colors.Grey01 + ) + } + + } + } else { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(20.dp), + contentPadding = PaddingValues(bottom = 20.dp), + modifier = Modifier.fillMaxSize() + ) { + items(filteredList, key = { it.id }) { alarm -> + CardAlarm( + badgeText = alarm.badgeText, + title = alarm.title, + message = alarm.message, + timeAgo = alarm.timeAgo, + isRead = alarm.isRead, + onClick = { + alarms = alarms.map { + if (it.id == alarm.id) it.copy(isRead = true) else it + } + }) + } + } + } + } + } +} + + +@Preview(showBackground = true) +@Composable +fun AlarmScreenPreview() { + ThipTheme { + AlarmScreen( + alarmItems = listOf( + AlarmItem(1, "피드", "내 글을 좋아합니다.", "user123님이 내 글에 좋아요를 눌렀어요.", "2", false), + AlarmItem(2, "모임", "같이 읽기를 시작했어요!", "모임방에서 20분 동안 같이 읽기가 시작되었어요!", "7", false), + AlarmItem(3, "피드", "내 글에 댓글이 달렸어요.", "user1: 진짜 공감합니다!", "2025.01.12", true), + AlarmItem(4, "모임", "투표가 시작되었어요!", "투표지를 먼저 열람합니다.", "17", false) + ) + ) + } +} + +@Preview(showBackground = true) +@Composable +fun AlarmScreenEmptyPreview() { + ThipTheme { + AlarmScreen( + alarmItems = emptyList() + ) + } +} \ No newline at end of file From 1d158d9fbac1305f61a2747992415851b9b3f160 Mon Sep 17 00:00:00 2001 From: Gyubin Date: Wed, 9 Jul 2025 20:41:04 +0900 Subject: [PATCH 23/50] =?UTF-8?q?[ui]:=20AlarmScreen=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20=EB=B0=8F=20CardAlarm=20=EB=B0=B0=EA=B2=BD=EC=83=89,=20?= =?UTF-8?q?=EB=B9=A8=EA=B0=84=20=EC=A0=90=20=EC=88=98=EC=A0=95=20(#36)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/common/alarmpage/screen/AlarmScreen.kt | 33 +++++++------------ .../texthip/thip/ui/common/cards/CardAlarm.kt | 11 ++++--- .../java/com/texthip/thip/ui/theme/Color.kt | 3 ++ 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt index e75881ef..cefec058 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt @@ -42,13 +42,11 @@ fun AlarmScreen( val filteredList = when { selectedStates[0] && !selectedStates[1] -> alarms.filter { it.badgeText == stringResource(R.string.alarm_feed) } !selectedStates[0] && selectedStates[1] -> alarms.filter { it.badgeText == stringResource(R.string.alarm_group) } - selectedStates[0] && selectedStates[1] -> alarms else -> alarms } Column( Modifier - .background(colors.Black) .fillMaxSize() ) { DefaultTopAppBar( @@ -57,7 +55,6 @@ fun AlarmScreen( ) Column( Modifier - .background(colors.Black) .fillMaxSize() .padding(horizontal = 20.dp) ) { @@ -69,29 +66,23 @@ fun AlarmScreen( Spacer(modifier = Modifier.height(20.dp)) if (filteredList.isEmpty()) { + Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - Icon( - painter = painterResource(R.drawable.ic_notification), - contentDescription = null, - tint = colors.Grey02, - ) - Spacer(modifier = Modifier.height(12.dp)) - Text( - text = stringResource(R.string.alarm_notification_comment), - style = typography.smalltitle_sb600_s16_h20, - color = colors.Grey01 - ) - } - + Icon( + painter = painterResource(R.drawable.ic_notification), + contentDescription = null, + tint = colors.Grey02, + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = stringResource(R.string.alarm_notification_comment), + style = typography.smalltitle_sb600_s16_h20, + color = colors.Grey01 + ) } } else { LazyColumn( diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt index 16dd30ad..71e90ff4 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -43,8 +44,8 @@ fun CardAlarm( message: String, timeAgo: String, isRead: Boolean = false, - containerColorUnread: Color = colors.DarkGrey, // 안읽음 상태의 배경색 - containerColorRead: Color = colors.DarkGrey02, // 읽음 상태의 배경색 + containerColorUnread: Color = colors.DarkGrey02, // 안읽음 상태의 배경색 + containerColorRead: Color = colors.DarkGrey03, // 읽음 상태의 배경색 onClick: () -> Unit = {} ) { Card( @@ -112,7 +113,6 @@ fun CardAlarm( ) { // 안읽음 상태일 때만 빨간 점 if (!isRead) { - Spacer(modifier = Modifier.width(8.dp)) Box( modifier = Modifier .size(6.dp) @@ -125,13 +125,16 @@ fun CardAlarm( text = timeAgo + stringResource(R.string.time_ago), style = typography.timedate_r400_s11, color = if (isRead) colors.Grey02 else colors.Grey01, + modifier = Modifier + .padding(top = 7.dp, end = 2.dp) + .offset(y = (-5).dp) ) } } } } - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(10.dp)) Text( text = message, diff --git a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt index 18710484..31961f3e 100644 --- a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt +++ b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt @@ -35,6 +35,7 @@ val Grey02 = Color(0xFF888888) val Grey03 = Color(0xFF525252) val DarkGrey = Color(0xFF3D3D3D) val DarkGrey50 = Color(0x803D3D3D) +val DarkGrey03 = Color(0xFF1D1D1D) val DarkGrey02 = Color(0xFF282828) val DarkGrey01 = Color(0x4B4B4B4B) val Black = Color(0xFF121212) @@ -71,6 +72,7 @@ data class ThipColors( val DarkGrey: Color, val darkGray01: Color, val DarkGrey50: Color, + val DarkGrey03: Color, val DarkGrey02: Color, val Black: Color, val Black50: Color, @@ -106,6 +108,7 @@ val defaultThipColors = ThipColors( DarkGrey = DarkGrey, darkGray01 = DarkGrey01, DarkGrey50 = DarkGrey50, + DarkGrey03 = DarkGrey03, DarkGrey02 = DarkGrey02, Black = Black, Black50 = Black50, From 9ce1fae69da89ae0d9dc9cf57a7dc5fca4418d96 Mon Sep 17 00:00:00 2001 From: JoGyuBin <128724038+rbqks529@users.noreply.github.com> Date: Thu, 3 Jul 2025 16:09:47 +0900 Subject: [PATCH 24/50] =?UTF-8?q?[ui]:=20=EB=82=B4=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EB=B0=A9=20Pager=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EC=99=84=EB=A3=8C=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 2 ++ .../ui/group/myroom/component/GenreChipRow.kt | 14 +++++++------ .../component/GroupDeadlineRoomSection.kt | 20 ++++++++++++------- .../group/myroom/component/GroupMainCard.kt | 2 +- .../ui/group/myroom/component/GroupPager.kt | 12 +++++++---- 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 1e536c6c..38860e7c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,8 @@ + + \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GenreChipRow.kt b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GenreChipRow.kt index ae3fa69a..37d41cee 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GenreChipRow.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GenreChipRow.kt @@ -1,11 +1,10 @@ package com.texthip.thip.ui.group.myroom.component -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.* 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.texthip.thip.ui.common.buttons.OptionChipButton @Composable @@ -15,8 +14,8 @@ fun GenreChipRow( onSelect: (Int) -> Unit ) { Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center ) { genres.forEachIndexed { idx, genre -> OptionChipButton( @@ -25,6 +24,9 @@ fun GenreChipRow( isSelected = selectedIndex == idx, onClick = { onSelect(idx) } ) + if (idx < genres.size - 1) { + Spacer(modifier = Modifier.width(4.dp)) + } } } } @@ -37,4 +39,4 @@ fun PreviewGenreChipRow() { selectedIndex = 0, onSelect = {} ) -} \ No newline at end of file +} diff --git a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt index c7e3f7a8..565bd1ef 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt @@ -6,12 +6,14 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.OutlinedTextFieldDefaults.contentPadding import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -29,8 +31,7 @@ fun GroupRoomDeadlineSection( roomSections: List, onRoomClick: (GroupCardItemRoomData) -> Unit ) { - val cardWidth = 320.dp - val pageSpacing = 12.dp + val sideMargin = 30.dp val pagerState = rememberPagerState( initialPage = 0, @@ -48,16 +49,21 @@ fun GroupRoomDeadlineSection( .height(588.dp), contentAlignment = Alignment.Center ) { - val horizontalPadding = ((maxWidth - cardWidth) / 2).coerceAtLeast(0.dp) + val horizontalPadding = sideMargin + val cardWidth = maxWidth - (horizontalPadding * 2) + val scale = 0.9f + val desiredGap = 12.dp // TODO: 이 부분을 10dp로 하면 양 옆의 카드에 살짝 다음 내용이 보여서 12정도가 어떤지 + + val pageSpacing = (-(cardWidth - (cardWidth * scale)) / 2) + desiredGap HorizontalPager( state = pagerState, - contentPadding = PaddingValues(horizontal = horizontalPadding), + contentPadding = PaddingValues(horizontal = 30.dp), pageSpacing = pageSpacing, modifier = Modifier.fillMaxWidth() ) { page -> val section = roomSections[page] - var selectedGenre by remember { mutableStateOf(0) } + var selectedGenre by remember { mutableIntStateOf(0) } val isCurrent = pagerState.currentPage == page val scale = if (isCurrent) 1f else 0.9f @@ -79,7 +85,7 @@ fun GroupRoomDeadlineSection( ), shape = RoundedCornerShape(14.dp) ) - .padding(vertical = 20.dp, horizontal = 12.dp) + .padding(vertical = 20.dp, horizontal = 20.dp) ) { Column( horizontalAlignment = Alignment.CenterHorizontally @@ -259,4 +265,4 @@ fun PreviewGroupRoomPagerSection() { onRoomClick = {} ) } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt index 98ac640b..9b5a2d6b 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt @@ -57,7 +57,7 @@ fun GroupMainCard( Card( modifier = Modifier - .width(320.dp) + .fillMaxWidth() .height(176.dp) .clickable { onClick() }, shape = RoundedCornerShape(18.dp), diff --git a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupPager.kt b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupPager.kt index 69147a66..3b2ab2a2 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupPager.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupPager.kt @@ -21,16 +21,20 @@ fun GroupPager( groupCards: List, onCardClick: (GroupCardData) -> Unit ) { - val cardWidth = 320.dp - val pageSpacing = 6.dp + val scale = 0.86f + val desiredGap = 10.dp BoxWithConstraints( modifier = Modifier .fillMaxWidth() .height(192.dp) ) { - val screenWidth = maxWidth - val horizontalPadding = ((screenWidth - cardWidth) / 2).coerceAtLeast(0.dp) + val horizontalPadding = 30.dp + val cardWidth = maxWidth - (horizontalPadding * 2) + + val pageSpacing = with(this) { + (-(cardWidth - (cardWidth * scale)) / 2f) + desiredGap + } val pagerState = rememberPagerState( initialPage = 0, From e5f0f03adb661cb70ff4d3dc513360a7f0db44f6 Mon Sep 17 00:00:00 2001 From: JoGyuBin <128724038+rbqks529@users.noreply.github.com> Date: Sat, 5 Jul 2025 00:21:46 +0900 Subject: [PATCH 25/50] =?UTF-8?q?[ui]:=20GroupMakeRoomScreen=20=EC=B1=85?= =?UTF-8?q?=20=EC=84=A0=ED=83=9D=20=EA=B5=AC=ED=98=84(=20(#35)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 1 - .../thip/ui/common/cards/CardBookSearch.kt | 10 -- .../ui/common/forms/SearchBookTextField.kt | 105 ++++++++++++++++++ .../component/BookListWithScrollbar.kt | 72 ++++++++++++ .../component/BookSearchBottomSheet.kt | 98 ++++++++++++++++ .../makeroom/component/GroupSelectBook.kt | 83 ++++++++++++++ .../ui/group/makeroom/mock/GroupBookData.kt | 17 +++ .../makeroom/screen/GroupMakeRoomScreen.kt | 79 +++++++++++++ .../main/res/drawable/ic_x_circle_grey.xml | 16 +++ app/src/main/res/values/strings.xml | 3 + 10 files changed, 473 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/texthip/thip/ui/common/forms/SearchBookTextField.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/group/makeroom/component/BookListWithScrollbar.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/group/makeroom/component/BookSearchBottomSheet.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupSelectBook.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/group/makeroom/mock/GroupBookData.kt create mode 100644 app/src/main/java/com/texthip/thip/ui/group/makeroom/screen/GroupMakeRoomScreen.kt create mode 100644 app/src/main/res/drawable/ic_x_circle_grey.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 38860e7c..62464c5c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ -