Skip to content

Commit 089c5e3

Browse files
authored
Merge pull request #56 from Nico1eKim/ui/#50-blank_pages
[UI] 데이터 없는 페이지들 구현
2 parents e95b216 + 29c3ed7 commit 089c5e3

25 files changed

Lines changed: 849 additions & 397 deletions

app/src/main/java/com/texthip/thip/ui/common/bottomsheet/MenuBottomSheet.kt

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,32 @@ fun MenuBottomSheet(
2727
CustomBottomSheet(
2828
onDismiss = onDismiss,
2929
) {
30-
items.forEachIndexed { index, item ->
31-
if (index > 0) {
32-
Spacer(modifier = Modifier.height(8.dp))
33-
HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03)
34-
Spacer(modifier = Modifier.height(8.dp))
35-
}
30+
Column(modifier = Modifier.padding(20.dp)) {
31+
items.forEachIndexed { index, item ->
32+
if (index > 0) {
33+
Spacer(modifier = Modifier.height(8.dp))
34+
HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03)
35+
Spacer(modifier = Modifier.height(8.dp))
36+
}
3637

37-
Column(
38-
modifier = Modifier
39-
.height(50.dp)
40-
.padding(horizontal = 12.dp, vertical = 8.dp),
41-
verticalArrangement = Arrangement.Center
42-
) {
43-
Text(
44-
text = item.text,
45-
style = typography.menu_m500_s16_h24,
46-
color = item.color,
38+
Column(
4739
modifier = Modifier
48-
.fillMaxWidth()
49-
.clickable {
50-
item.onClick()
51-
onDismiss()
52-
}
53-
)
40+
.height(50.dp)
41+
.padding(horizontal = 12.dp, vertical = 8.dp),
42+
verticalArrangement = Arrangement.Center
43+
) {
44+
Text(
45+
text = item.text,
46+
style = typography.menu_m500_s16_h24,
47+
color = item.color,
48+
modifier = Modifier
49+
.fillMaxWidth()
50+
.clickable {
51+
item.onClick()
52+
onDismiss()
53+
}
54+
)
55+
}
5456
}
5557
}
5658
}

app/src/main/java/com/texthip/thip/ui/common/buttons/OptionChipButton.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ fun OptionChipButton(
3232
modifier: Modifier = Modifier,
3333
text: String,
3434
isFilled: Boolean = false,
35-
isSelected: Boolean? = null, // 추가
35+
isSelected: Boolean? = null,
3636
enabled: Boolean = true,
3737
textStyle: TextStyle = typography.info_r400_s12,
3838
onClick: () -> Unit,
39+
onDisabledClick: () -> Unit = { }
3940
) {
4041
var isClicked by remember { mutableStateOf(false) }
4142
val checked = isSelected ?: isClicked
@@ -69,9 +70,13 @@ fun OptionChipButton(
6970
color = borderColor,
7071
shape = RoundedCornerShape(20.dp)
7172
)
72-
.clickable(enabled = enabled) {
73-
if (isSelected == null) isClicked = !isClicked
74-
onClick()
73+
.clickable {
74+
if (enabled) {
75+
if (isSelected == null) isClicked = !isClicked
76+
onClick()
77+
} else {
78+
onDisabledClick.invoke()
79+
}
7580
}
7681
.height(30.dp)
7782
.padding(horizontal = 12.dp),

app/src/main/java/com/texthip/thip/ui/common/cards/CardCommentGroup.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import com.texthip.thip.ui.theme.ThipTheme.typography
1717

1818
@Composable
1919
fun CardCommentGroup(
20-
data: GroupRoomChatData
20+
data: GroupRoomChatData,
21+
onMenuClick: () -> Unit
2122
) {
2223
Column(
2324
modifier = Modifier
@@ -27,7 +28,8 @@ fun CardCommentGroup(
2728
ProfileBarWithDate(
2829
profileImage = data.profileImage,
2930
nickname = data.nickname,
30-
dateText = data.date
31+
dateText = data.date,
32+
onMenuClick = onMenuClick
3133
)
3234
Spacer(Modifier.height(8.dp))
3335
Text(
@@ -47,7 +49,9 @@ private fun CardCommentGroupPreview() {
4749
profileImage = null,
4850
nickname = "user.01",
4951
date = "11시간 전",
50-
content = "이것은 그룹 채팅의 댓글입니다. 이곳에 댓글 내용을 작성할 수 있습니다. 여러 줄로 작성해도 됩니다."
51-
)
52+
content = "이것은 그룹 채팅의 댓글입니다. 이곳에 댓글 내용을 작성할 수 있습니다. 여러 줄로 작성해도 됩니다.",
53+
isMine = false
54+
),
55+
onMenuClick = {}
5256
)
5357
}
Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.texthip.thip.ui.common.cards
22

33
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.clickable
45
import androidx.compose.foundation.layout.Arrangement
56
import androidx.compose.foundation.layout.Box
67
import androidx.compose.foundation.layout.Column
78
import androidx.compose.foundation.layout.Row
89
import androidx.compose.foundation.layout.fillMaxWidth
10+
import androidx.compose.foundation.layout.height
911
import androidx.compose.foundation.layout.padding
1012
import androidx.compose.foundation.layout.size
1113
import androidx.compose.foundation.pager.HorizontalPager
@@ -14,9 +16,7 @@ import androidx.compose.foundation.shape.CircleShape
1416
import androidx.compose.foundation.shape.RoundedCornerShape
1517
import androidx.compose.material3.Text
1618
import androidx.compose.runtime.Composable
17-
import androidx.compose.runtime.mutableStateMapOf
18-
import androidx.compose.runtime.remember
19-
import androidx.compose.runtime.toMutableStateList
19+
import androidx.compose.ui.Alignment
2020
import androidx.compose.ui.Modifier
2121
import androidx.compose.ui.res.stringResource
2222
import androidx.compose.ui.tooling.preview.Preview
@@ -30,17 +30,12 @@ import com.texthip.thip.ui.theme.ThipTheme.typography
3030

3131
@Composable
3232
fun CardVote(
33-
voteData: List<VoteData>
33+
voteData: List<VoteData>,
34+
onVoteClick: (VoteData) -> Unit = {}
3435
) {
3536
val pageCount = voteData.size
3637
val pagerState = rememberPagerState(pageCount = { pageCount })
3738

38-
// 각 페이지별 상태 기억: 선택 인덱스, 선택 여부 포함한 voteItems
39-
val selectedIndexes = remember { mutableStateMapOf<Int, Int?>() }
40-
val voteItemStates = remember {
41-
voteData.map { it.voteItems.toMutableStateList() }.toMutableStateList()
42-
}
43-
4439
Column(
4540
modifier = Modifier
4641
.fillMaxWidth()
@@ -55,52 +50,65 @@ fun CardVote(
5550
modifier = Modifier.padding(horizontal = 12.dp)
5651
)
5752

58-
HorizontalPager(
59-
state = pagerState,
60-
modifier = Modifier.fillMaxWidth()
61-
) { page ->
62-
val voteItems = voteItemStates[page]
63-
val selectedIndex = selectedIndexes[page]
64-
val hasVoted = voteItems.any { it.isVoted }
65-
66-
Column(
67-
modifier = Modifier.padding(horizontal = 12.dp),
68-
verticalArrangement = Arrangement.spacedBy(10.dp)
53+
if (voteData.isEmpty()) {
54+
Box(
55+
modifier = Modifier
56+
.fillMaxWidth()
57+
.padding(top = 12.dp)
58+
.padding(vertical = 60.dp),
59+
contentAlignment = Alignment.Center
6960
) {
7061
Text(
71-
text = voteData[page].description,
62+
text = stringResource(R.string.no_vote),
7263
style = typography.info_m500_s12,
73-
color = colors.White,
74-
)
75-
76-
GroupVoteButton(
77-
voteItems = voteItems,
78-
selectedIndex = selectedIndex,
79-
hasVoted = hasVoted,
80-
onOptionSelected = { index ->
81-
selectedIndexes[page] = if (selectedIndex == index) null else index
82-
83-
voteItemStates[page] = voteItems.mapIndexed { i, item ->
84-
item.copy(isVoted = i == index && selectedIndex != index)
85-
}.toMutableStateList()
86-
}
64+
color = colors.Grey
8765
)
8866
}
89-
}
67+
} else {
68+
HorizontalPager(
69+
state = pagerState,
70+
modifier = Modifier.fillMaxWidth()
71+
) { page ->
72+
val vote = voteData[page]
73+
val voteItems = vote.voteItems.take(3) // 최대 3개만
9074

91-
Row(
92-
Modifier
93-
.fillMaxWidth(),
94-
horizontalArrangement = Arrangement.Center
95-
) {
96-
repeat(pageCount) { iteration ->
97-
val color = if (pagerState.currentPage == iteration) colors.White else colors.Grey02
98-
Box(
75+
Column(
9976
modifier = Modifier
77+
.height(176.dp)
10078
.padding(horizontal = 12.dp)
101-
.background(color, CircleShape)
102-
.size(4.dp)
103-
)
79+
.clickable { onVoteClick(vote) }, // 전체 클릭 시 이동
80+
verticalArrangement = Arrangement.spacedBy(10.dp)
81+
) {
82+
Text(
83+
text = vote.description,
84+
style = typography.info_m500_s12,
85+
color = colors.White,
86+
)
87+
88+
GroupVoteButton(
89+
voteItems = voteItems,
90+
selectedIndex = null, // 표시용이므로 선택 없음
91+
hasVoted = false, // 투표 상태 없음
92+
onOptionSelected = { onVoteClick(vote) } // 어떤 항목을 눌러도 이동
93+
)
94+
}
95+
}
96+
97+
Row(
98+
Modifier
99+
.fillMaxWidth(),
100+
horizontalArrangement = Arrangement.Center
101+
) {
102+
repeat(pageCount) { iteration ->
103+
val color =
104+
if (pagerState.currentPage == iteration) colors.White else colors.Grey02
105+
Box(
106+
modifier = Modifier
107+
.padding(horizontal = 12.dp)
108+
.background(color, CircleShape)
109+
.size(4.dp)
110+
)
111+
}
104112
}
105113
}
106114
}
@@ -109,5 +117,13 @@ fun CardVote(
109117
@Preview
110118
@Composable
111119
private fun CardVotePreview() {
112-
CardVote(voteData = mockVoteData)
120+
Column(
121+
modifier = Modifier
122+
.fillMaxWidth()
123+
.padding(16.dp),
124+
verticalArrangement = Arrangement.spacedBy(16.dp)
125+
) {
126+
CardVote(voteData = mockVoteData)
127+
CardVote(voteData = emptyList())
128+
}
113129
}

app/src/main/java/com/texthip/thip/ui/common/forms/CommentTextField.kt

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import androidx.compose.foundation.layout.Box
66
import androidx.compose.foundation.layout.Column
77
import androidx.compose.foundation.layout.Row
88
import androidx.compose.foundation.layout.Spacer
9+
import androidx.compose.foundation.layout.defaultMinSize
910
import androidx.compose.foundation.layout.fillMaxWidth
1011
import androidx.compose.foundation.layout.height
1112
import androidx.compose.foundation.layout.padding
1213
import androidx.compose.foundation.layout.size
1314
import androidx.compose.foundation.layout.width
15+
import androidx.compose.foundation.layout.wrapContentHeight
1416
import androidx.compose.foundation.shape.RoundedCornerShape
1517
import androidx.compose.foundation.text.BasicTextField
1618
import androidx.compose.material3.Icon
@@ -93,37 +95,41 @@ fun CommentTextField(
9395
modifier = Modifier
9496
.fillMaxWidth()
9597
.padding(horizontal = 20.dp, vertical = 10.dp)
96-
.height(36.dp)
9798
.background(colors.DarkGrey, shape = RoundedCornerShape(20.dp)),
9899
verticalAlignment = Alignment.CenterVertically
99100
) {
100101
BasicTextField(
101102
value = input,
102103
onValueChange = onInputChange,
103-
singleLine = true,
104+
maxLines = 5,
104105
textStyle = typography.menu_r400_s14_h24.copy(color = colors.White),
105106
modifier = Modifier
106107
.weight(1f)
107-
.padding(start = 12.dp),
108+
.padding(start = 12.dp, top = 4.dp, bottom = 4.dp, end = 12.dp)
109+
.defaultMinSize(minHeight = 36.dp)
110+
.wrapContentHeight(), // 높이 자동 확장
108111
cursorBrush = SolidColor(colors.NeonGreen),
109112
decorationBox = { innerTextField ->
110-
if (input.isEmpty()) {
111-
Text(
112-
text = hint,
113-
color = colors.Grey02,
114-
style = typography.menu_r400_s14_h24
115-
)
113+
Box {
114+
if (input.isEmpty()) {
115+
Text(
116+
text = hint,
117+
color = colors.Grey02,
118+
style = typography.menu_r400_s14_h24
119+
)
120+
}
121+
innerTextField()
116122
}
117-
innerTextField()
118123
}
119124
)
120125

121126
// 전송 버튼
122127
val isEnabled = input.isNotBlank()
123128
Box(
124129
modifier = Modifier
125-
.padding(end = 4.dp)
130+
.padding(end = 8.dp, bottom = 8.dp)
126131
.size(width = 42.dp, height = 28.dp)
132+
.align(Alignment.Bottom)
127133
.background(
128134
color = if (isEnabled) colors.Purple else colors.Grey02,
129135
shape = RoundedCornerShape(20.dp)

0 commit comments

Comments
 (0)