From 91c44a163d3b4480f3896fa23eface3180df9151 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 10 Jul 2025 19:16:47 +0900 Subject: [PATCH 01/22] =?UTF-8?q?[ui]:=20floating=20button=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/buttons/ExpandableFloatingButton.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/ExpandableFloatingButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/ExpandableFloatingButton.kt index a9378da4..48b318e5 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/ExpandableFloatingButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/ExpandableFloatingButton.kt @@ -65,7 +65,7 @@ fun ExpandableFloatingButton( ) { Column( modifier = Modifier - .padding(bottom = 94.dp, end = 20.dp) + .padding(bottom = 62.dp) .width(184.dp) .background( color = colors.Black, @@ -100,8 +100,7 @@ fun ExpandableFloatingButton( contentColor = colors.NeonGreen, shape = CircleShape, modifier = Modifier - .padding(16.dp) - .size(56.dp) + .size(50.dp) .border(width = 2.dp, color = colors.NeonGreen50, shape = CircleShape) ) { Icon( From 5d6be30b0dbf5c92f88f628df69c34c33bb55713 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:10:11 +0900 Subject: [PATCH 02/22] =?UTF-8?q?[ui]:=20toggle=20button=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt index 5e70609c..624889e5 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt @@ -2,6 +2,7 @@ package com.texthip.thip.ui.common.buttons import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Icon import androidx.compose.material3.Switch @@ -24,9 +25,8 @@ fun ToggleSwitchButton( isChecked: Boolean, onToggleChange: (Boolean) -> Unit ) { - //var isChecked by remember { mutableStateOf(true) } Switch( - modifier = Modifier.padding(4.dp), + modifier = Modifier.height(30.dp), checked = isChecked, onCheckedChange = onToggleChange, colors = SwitchDefaults.colors( From 06f806e0fb65cb015e5a3da320d1eea379dc6fdd Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:10:29 +0900 Subject: [PATCH 03/22] =?UTF-8?q?[ui]:=20book=20page=20text=20field=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=88=98=EC=A0=95=20(#3?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/forms/BookPageTextField.kt | 107 +++++++++++------- .../main/res/drawable/ic_x_circle_grey.xml | 14 +-- app/src/main/res/values/strings.xml | 9 +- 3 files changed, 77 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt index fe832cae..2530ae5d 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt @@ -1,11 +1,12 @@ package com.texthip.thip.ui.common.forms +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions @@ -41,27 +42,28 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun BookPageTextField( modifier: Modifier = Modifier, - bookPage: Int + bookTotalPage: Int, + enabled: Boolean = true, + text: String, + onValueChange: (String) -> Unit, ) { - var text by rememberSaveable { mutableStateOf("") } var isError by rememberSaveable { mutableStateOf(false) } var errorMessageRes by rememberSaveable { mutableStateOf(null) } - var errorMessageParam by rememberSaveable { mutableStateOf(0) } Column { OutlinedTextField( value = text, onValueChange = { newText: String -> if (newText.isEmpty() || newText.all { it.isDigit() }) { - text = newText + onValueChange(newText) + if (newText.isNotEmpty()) { val pageNum = newText.toInt() - isError = pageNum > bookPage - if (isError) { - errorMessageRes = R.string.error_page_over - errorMessageParam = bookPage + isError = pageNum > bookTotalPage + errorMessageRes = if (isError) { + R.string.error_page_over } else { - errorMessageRes = null + null } } else { isError = false @@ -69,51 +71,63 @@ fun BookPageTextField( } } }, - visualTransformation = SuffixTransformation( - suffix = "/${bookPage}p", - suffixColor = colors.Grey02 - ), + enabled = enabled, + visualTransformation = if (enabled) { + SuffixTransformation("/${bookTotalPage}p", colors.Grey02) + } else { + VisualTransformation.None + }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - modifier = modifier.size(width = 320.dp, height = 48.dp), + modifier = modifier + .size(width = 320.dp, height = 48.dp) + .then( + if (isError) + Modifier.border( + width = 1.dp, + color = colors.Red, + shape = RoundedCornerShape(12.dp) + ) + else Modifier + ), textStyle = typography.menu_r400_s14_h24.copy(lineHeight = 12.sp), maxLines = 1, shape = RoundedCornerShape(12.dp), colors = TextFieldDefaults.colors( focusedTextColor = colors.White, - focusedIndicatorColor = if (isError) colors.Red else Color.Transparent, - unfocusedIndicatorColor = if (isError) colors.Red else Color.Transparent, - focusedContainerColor = colors.Black, - unfocusedContainerColor = colors.Black, - cursorColor = colors.NeonGreen + disabledTextColor = colors.White, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + focusedContainerColor = colors.DarkGrey02, + unfocusedContainerColor = colors.DarkGrey02, + disabledContainerColor = colors.DarkGrey02, + cursorColor = colors.NeonGreen, ), trailingIcon = { - if (text.isNotEmpty()) { - Icon( - painter = painterResource(id = R.drawable.ic_x_circle_white), - contentDescription = "Clear text", - modifier = Modifier.clickable { - text = "" + Icon( + painter = painterResource(id = R.drawable.ic_x_circle_grey), + contentDescription = "Clear text", + modifier = Modifier.clickable { + if (text.isNotEmpty()) { + onValueChange("") isError = false errorMessageRes = null - }, - tint = Color.Unspecified - ) - } else { - Icon( - painter = painterResource(id = R.drawable.ic_x_circle), - contentDescription = "Clear text" - ) - } + } + }, + tint = Color.Unspecified + ) } ) - if (isError && errorMessageRes != null) { - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = stringResource(id = errorMessageRes!!, errorMessageParam), - color = colors.Red, - style = typography.menu_r400_s14_h24.copy(lineHeight = 12.sp) - ) + Box(modifier = Modifier.height(22.dp)) { + if (isError && errorMessageRes != null) { + Text( + modifier = Modifier.padding(start = 4.dp, top = 8.dp), + text = stringResource(id = errorMessageRes!!), + color = colors.Red, + style = typography.menu_r400_s14_h24.copy(lineHeight = 12.sp) + ) + } } } } @@ -135,6 +149,7 @@ class SuffixTransformation( val offsetMapping = object : OffsetMapping { override fun originalToTransformed(offset: Int): Int = offset.coerceAtMost(original.length) + override fun transformedToOriginal(offset: Int): Int = offset.coerceAtMost(original.length) } @@ -147,12 +162,18 @@ class SuffixTransformation( @Composable @Preview(showBackground = true, backgroundColor = 0xFF000000, widthDp = 360, heightDp = 200) fun BookPageTextFieldPreviewEmpty() { + var text by rememberSaveable { mutableStateOf("") } + Box( modifier = Modifier.size(width = 360.dp, height = 200.dp), contentAlignment = Alignment.Center ) { BookPageTextField( - bookPage = 456 + bookTotalPage = 456, + text = text, + onValueChange = { + text = it + } ) } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_x_circle_grey.xml b/app/src/main/res/drawable/ic_x_circle_grey.xml index 300f0c30..b30ba54b 100644 --- a/app/src/main/res/drawable/ic_x_circle_grey.xml +++ b/app/src/main/res/drawable/ic_x_circle_grey.xml @@ -1,16 +1,16 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c2ab39ae..62cfde27 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -52,9 +52,6 @@ 기둝μž₯ πŸ”₯λͺ¨μž„λ°©μ˜ 뜨거운 감자 - - ν•΄λ‹Ή λ„μ„œλŠ” %1$dpκΉŒμ§€λ§Œ μžˆμŠ΅λ‹ˆλ‹€. - λ‹˜μ˜ κ΅¬λ…μž λ‹€μŒ @@ -153,6 +150,8 @@ λ°© λ‚˜κ°€κΈ° λ°© μ‹ κ³ ν•˜κΈ° λ°© μ‚­μ œν•˜κΈ° + + ~ p κ·Έλ£Ή 기둝 @@ -164,6 +163,10 @@ \@ \ 00λ‹˜μ—κ²Œ λŒ“κΈ€μ„ λ‚¨κ²¨λ³΄μ„Έμš”. + 기둝할 νŽ˜μ΄μ§€ + 총평 + μ „μ²΄λ²”μœ„ + μ „μ²΄νŽ˜μ΄μ§€λ₯Ό μ΄ˆκ³Όν•  수 μ—†μ–΄μš”. ν”Όλ“œ From a0abca09a0846a39abe4d1db517393c0072f112b Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:10:45 +0900 Subject: [PATCH 04/22] =?UTF-8?q?[ui]:=20=EA=B8=B0=EB=A1=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=ED=99=94=EB=A9=B4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EA=B9=8C=EC=A7=80=20=EC=99=84=EB=A3=8C=20(#3?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../note/screen/GroupNoteCreateScreen.kt | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt new file mode 100644 index 00000000..7e2b7508 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -0,0 +1,123 @@ +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.height +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.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.ToggleSwitchButton +import com.texthip.thip.ui.common.forms.BookPageTextField +import com.texthip.thip.ui.common.topappbar.InputTopAppBar +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 GroupNoteCreateScreen() { + var pageText by rememberSaveable { mutableStateOf("") } + var isGeneralReview by rememberSaveable { mutableStateOf(false) } + + val allRangeText = stringResource(R.string.all_range) + + Column( + modifier = Modifier.fillMaxSize() + ) { + InputTopAppBar( + title = stringResource(R.string.write_record), + isRightButtonEnabled = false, + onLeftClick = { /* λ’€λ‘œκ°€κΈ° λ™μž‘ */ }, + onRightClick = { /* μ™„λ£Œ λ™μž‘ */ } + ) + + Column( + modifier = Modifier + .padding(vertical = 32.dp, horizontal = 20.dp), + verticalArrangement = Arrangement.spacedBy(32.dp), + ) { + Column( + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + text = stringResource(R.string.page_to_record), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White + ) + + Box( + modifier = Modifier.height(90.dp), + ) { + BookPageTextField( + modifier = Modifier.fillMaxWidth(), + bookTotalPage = 500, // TODO: μ„œλ²„ λ°μ΄ν„°λ‘œ μˆ˜μ • + text = if (isGeneralReview) stringResource(R.string.all_range) else pageText, + onValueChange = { + if (!isGeneralReview) pageText = it + }, + enabled = !isGeneralReview + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomEnd), + horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End), + verticalAlignment = Alignment.CenterVertically + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(R.drawable.ic_information), + contentDescription = null, + tint = colors.Grey02 + ) + + Text( + text = stringResource(R.string.general_review), + style = typography.info_r400_s12, + color = colors.Grey + ) + } + + ToggleSwitchButton( + isChecked = isGeneralReview + ) { checked -> + isGeneralReview = checked + pageText = if (checked) { + allRangeText + } else { + "" + } + } + } + } + } + } + } +} + +@Preview +@Composable +private fun GroupNoteCreateScreenPreview() { + ThipTheme { + GroupNoteCreateScreen() + } +} \ No newline at end of file From 4bf2f4b46e3ea8080b723709b501f6c97e26ef8e Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:46:04 +0900 Subject: [PATCH 05/22] =?UTF-8?q?[chore]:=20=EC=A4=91=EB=B3=B5=EB=90=98?= =?UTF-8?q?=EB=8A=94=20string=20=EA=B5=90=EC=B2=B4=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt | 2 +- app/src/main/res/values/strings.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt index 8fa6adf6..ac3c489c 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupRoomScreen.kt @@ -170,7 +170,7 @@ fun GroupRoomScreen( Spacer(Modifier.width(2.dp)) Text( text = stringResource( - R.string.group_room_screen_participant_count_max, + R.string.card_item_participant_count_max, detail.maxMembers ), style = typography.info_m500_s12, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 62cfde27..da5dac49 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -126,7 +126,6 @@ "%1$sλ‹˜μ˜ 진행도 " λͺ¨μž„λ°© μ°Έμ—¬ν•  μ‚¬λžŒ! %1$s - / %1$sλͺ… %1$s일 λ‚¨μŒ μ°Έμ—¬ν•˜κΈ° μ°Έμ—¬ μ·¨μ†Œν•˜κΈ° @@ -167,6 +166,8 @@ 총평 μ „μ²΄λ²”μœ„ μ „μ²΄νŽ˜μ΄μ§€λ₯Ό μ΄ˆκ³Όν•  수 μ—†μ–΄μš”. + μ§€κΈˆ 읽은 κ·Έ λΆ€λΆ„, μ–΄λ• λ‚˜μš”? + ...ν•œ 생각이 λ“€μ—ˆμ–΄μš”.πŸ€” ν”Όλ“œ From d192aeb7c607e7a1a0d151e14fac707faa3004ce Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:46:21 +0900 Subject: [PATCH 06/22] =?UTF-8?q?[ui]:=20=EA=B8=B0=EB=B3=B8=20textfield=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1=20(#3?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/forms/DefaultTextField.kt | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt new file mode 100644 index 00000000..86c4a69c --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt @@ -0,0 +1,87 @@ +package com.texthip.thip.ui.common.forms + +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.fillMaxWidth +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.SolidColor +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.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun DefaultTextField( + text: String, + onTextChange: (String) -> Unit, + hint: String = stringResource(R.string.my_opinion_placeholder), + maxLength: Int = 500 +) { + val isOverLimit = text.length > maxLength + val displayCount = if (text.length > maxLength) maxLength else text.length + + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + Box( + modifier = Modifier.fillMaxWidth() + ) { + BasicTextField( + value = text, + onValueChange = { + if (it.length <= maxLength) onTextChange(it) + }, + textStyle = typography.menu_r400_s14_h24.copy(color = colors.White), + modifier = Modifier + .fillMaxWidth(), + cursorBrush = SolidColor(colors.NeonGreen), + decorationBox = { innerTextField -> + Box( + modifier = Modifier.background(color = colors.Black) + ) { + if (text.isEmpty()) { + Text( + text = hint, + color = colors.Grey02, + style = typography.menu_r400_s14_h24 + ) + } + innerTextField() + } + } + ) + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Text( + text = stringResource(R.string.group_input_count, displayCount, maxLength), + color = if (isOverLimit) colors.Red else colors.NeonGreen, + style = typography.info_r400_s12 + ) + } + } +} + +@Preview +@Composable +private fun DefaultTextFieldPreview() { + var text by rememberSaveable { mutableStateOf("") } + + DefaultTextField( + text = text, + onTextChange = { text = it } + ) +} \ No newline at end of file From 8e5ac80f1b515724eb04e64bc0d8c6530b893d48 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:46:42 +0900 Subject: [PATCH 07/22] =?UTF-8?q?[ui]:=20=EA=B8=B0=EB=A1=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=ED=99=94=EB=A9=B4=20=EC=9D=98=EA=B2=AC=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EB=B6=80=EB=B6=84=EA=B9=8C=EC=A7=80=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group/note/screen/GroupNoteCreateScreen.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt index 7e2b7508..6a657da6 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.common.buttons.ToggleSwitchButton import com.texthip.thip.ui.common.forms.BookPageTextField +import com.texthip.thip.ui.common.forms.DefaultTextField import com.texthip.thip.ui.common.topappbar.InputTopAppBar import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors @@ -36,6 +37,8 @@ fun GroupNoteCreateScreen() { val allRangeText = stringResource(R.string.all_range) + var opinionText by rememberSaveable { mutableStateOf("") } + Column( modifier = Modifier.fillMaxSize() ) { @@ -110,6 +113,21 @@ fun GroupNoteCreateScreen() { } } } + + Column( + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + text = stringResource(R.string.my_opinion_title), + style = typography.smalltitle_sb600_s18_h24, + color = colors.White + ) + + DefaultTextField( + text = opinionText, + onTextChange = { opinionText = it } + ) + } } } } From 9055cba9ca147d6d0a1cd34b97412e02ef28089b Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:50:52 +0900 Subject: [PATCH 08/22] =?UTF-8?q?[ui]:=20=EA=B8=B0=EB=A1=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=ED=99=94=EB=A9=B4=20form=20=EC=B1=84=EC=9B=8C?= =?UTF-8?q?=EC=A7=80=EB=A9=B4=20=EC=99=84=EB=A3=8C=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=EC=8B=9C=ED=82=A4=EA=B8=B0=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/group/note/screen/GroupNoteCreateScreen.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt index 6a657da6..e82aeee3 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -39,12 +39,14 @@ fun GroupNoteCreateScreen() { var opinionText by rememberSaveable { mutableStateOf("") } + val isFormFilled = pageText.isNotBlank() && opinionText.isNotBlank() + Column( modifier = Modifier.fillMaxSize() ) { InputTopAppBar( title = stringResource(R.string.write_record), - isRightButtonEnabled = false, + isRightButtonEnabled = isFormFilled, onLeftClick = { /* λ’€λ‘œκ°€κΈ° λ™μž‘ */ }, onRightClick = { /* μ™„λ£Œ λ™μž‘ */ } ) From da0fa14d226ae477b4f791235dbcf188e1a162cb Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:51:11 +0900 Subject: [PATCH 09/22] =?UTF-8?q?[ui]:=20book=20page=20textfield=20unfocus?= =?UTF-8?q?ed=20text=20color=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/texthip/thip/ui/common/forms/BookPageTextField.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt index 2530ae5d..3061c3f9 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/BookPageTextField.kt @@ -94,6 +94,7 @@ fun BookPageTextField( shape = RoundedCornerShape(12.dp), colors = TextFieldDefaults.colors( focusedTextColor = colors.White, + unfocusedTextColor = colors.White, disabledTextColor = colors.White, focusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent, From 02a69a25e72d5622f9e58eae621411257ec9c26a Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 16:28:03 +0900 Subject: [PATCH 10/22] =?UTF-8?q?[refactor]:=20=ED=99=94=EB=A9=B4=20input?= =?UTF-8?q?=20section=EB=93=A4=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../note/component/OpinionInputSection.kt} | 17 ++- .../group/note/component/PageInputSection.kt | 111 ++++++++++++++++++ .../note/screen/GroupNoteCreateScreen.kt | 101 ++-------------- 3 files changed, 136 insertions(+), 93 deletions(-) rename app/src/main/java/com/texthip/thip/ui/{common/forms/DefaultTextField.kt => group/note/component/OpinionInputSection.kt} (87%) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/OpinionInputSection.kt similarity index 87% rename from app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt rename to app/src/main/java/com/texthip/thip/ui/group/note/component/OpinionInputSection.kt index 86c4a69c..81eadf69 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/DefaultTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/OpinionInputSection.kt @@ -1,4 +1,4 @@ -package com.texthip.thip.ui.common.forms +package com.texthip.thip.ui.group.note.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -23,7 +23,8 @@ import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @Composable -fun DefaultTextField( +fun OpinionInputSection( + title: String = stringResource(R.string.my_opinion_title), text: String, onTextChange: (String) -> Unit, hint: String = stringResource(R.string.my_opinion_placeholder), @@ -32,7 +33,13 @@ fun DefaultTextField( val isOverLimit = text.length > maxLength val displayCount = if (text.length > maxLength) maxLength else text.length - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + Text( + text = title, + style = typography.smalltitle_sb600_s18_h24, + color = colors.White + ) + Box( modifier = Modifier.fillMaxWidth() ) { @@ -77,10 +84,10 @@ fun DefaultTextField( @Preview @Composable -private fun DefaultTextFieldPreview() { +private fun OpinionInputSectionPreview() { var text by rememberSaveable { mutableStateOf("") } - DefaultTextField( + OpinionInputSection( text = text, onTextChange = { text = it } ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt new file mode 100644 index 00000000..748b68a3 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt @@ -0,0 +1,111 @@ +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.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +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.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.ToggleSwitchButton +import com.texthip.thip.ui.common.forms.BookPageTextField +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun PageInputSection( + title: String = stringResource(R.string.page_to_record), + pageText: String, + onPageTextChange: (String) -> Unit, + isGeneralReview: Boolean, + onGeneralReviewToggle: (Boolean) -> Unit, + bookTotalPage: Int +) { + val allRangeText = stringResource(R.string.all_range) + + Column( + modifier = Modifier, + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + text = title, + style = typography.smalltitle_sb600_s18_h24, + color = colors.White + ) + + Box( + modifier = Modifier.height(90.dp), + ) { + BookPageTextField( + modifier = Modifier.fillMaxWidth(), + bookTotalPage = bookTotalPage, + text = if (isGeneralReview) allRangeText else pageText, + onValueChange = { + if (!isGeneralReview) onPageTextChange(it) + }, + enabled = !isGeneralReview + ) + + Row( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomEnd), + horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End), + verticalAlignment = Alignment.CenterVertically + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(R.drawable.ic_information), + contentDescription = null, + tint = colors.Grey02 + ) + + Text( + text = stringResource(R.string.general_review), + style = typography.info_r400_s12, + color = colors.Grey + ) + } + + ToggleSwitchButton( + isChecked = isGeneralReview, + onToggleChange = { checked -> + onGeneralReviewToggle(checked) + onPageTextChange(if (checked) allRangeText else "") + } + ) + } + } + } +} + +@Preview +@Composable +private fun PageInputSectionPreview() { + var pageText by rememberSaveable { mutableStateOf("") } + var isGeneralReview by rememberSaveable { mutableStateOf(false) } + + PageInputSection( + pageText = pageText, + onPageTextChange = { pageText = it }, + isGeneralReview = isGeneralReview, + onGeneralReviewToggle = { isGeneralReview = it }, + bookTotalPage = 500, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt index e82aeee3..c918a95d 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -1,42 +1,28 @@ 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.height 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.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.ToggleSwitchButton -import com.texthip.thip.ui.common.forms.BookPageTextField -import com.texthip.thip.ui.common.forms.DefaultTextField import com.texthip.thip.ui.common.topappbar.InputTopAppBar +import com.texthip.thip.ui.group.note.component.OpinionInputSection +import com.texthip.thip.ui.group.note.component.PageInputSection 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 GroupNoteCreateScreen() { var pageText by rememberSaveable { mutableStateOf("") } var isGeneralReview by rememberSaveable { mutableStateOf(false) } - - val allRangeText = stringResource(R.string.all_range) - var opinionText by rememberSaveable { mutableStateOf("") } val isFormFilled = pageText.isNotBlank() && opinionText.isNotBlank() @@ -56,80 +42,19 @@ fun GroupNoteCreateScreen() { .padding(vertical = 32.dp, horizontal = 20.dp), verticalArrangement = Arrangement.spacedBy(32.dp), ) { - Column( - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - Text( - text = stringResource(R.string.page_to_record), - style = typography.smalltitle_sb600_s18_h24, - color = colors.White - ) - - Box( - modifier = Modifier.height(90.dp), - ) { - BookPageTextField( - modifier = Modifier.fillMaxWidth(), - bookTotalPage = 500, // TODO: μ„œλ²„ λ°μ΄ν„°λ‘œ μˆ˜μ • - text = if (isGeneralReview) stringResource(R.string.all_range) else pageText, - onValueChange = { - if (!isGeneralReview) pageText = it - }, - enabled = !isGeneralReview - ) - - Row( - modifier = Modifier - .fillMaxWidth() - .align(Alignment.BottomEnd), - horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End), - verticalAlignment = Alignment.CenterVertically - ) { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - painter = painterResource(R.drawable.ic_information), - contentDescription = null, - tint = colors.Grey02 - ) - - Text( - text = stringResource(R.string.general_review), - style = typography.info_r400_s12, - color = colors.Grey - ) - } - - ToggleSwitchButton( - isChecked = isGeneralReview - ) { checked -> - isGeneralReview = checked - pageText = if (checked) { - allRangeText - } else { - "" - } - } - } - } - } + PageInputSection( + pageText = pageText, + onPageTextChange = { pageText = it }, + isGeneralReview = isGeneralReview, + onGeneralReviewToggle = { isGeneralReview = it }, + bookTotalPage = 500 // TODO: μ„œλ²„ λ°μ΄ν„°λ‘œ λ³€κ²½ + ) - Column( - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - Text( - text = stringResource(R.string.my_opinion_title), - style = typography.smalltitle_sb600_s18_h24, - color = colors.White - ) + OpinionInputSection( + text = opinionText, + onTextChange = { opinionText = it } + ) - DefaultTextField( - text = opinionText, - onTextChange = { opinionText = it } - ) - } } } } From 080de41492e15502fbc8dd0726b6c95f0aa17149 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Mon, 14 Jul 2025 17:22:00 +0900 Subject: [PATCH 11/22] =?UTF-8?q?[refactor]:=20bordered=20text=20field=20t?= =?UTF-8?q?ext=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/forms/BorderedTextField.kt | 60 +++++++++++-------- .../res/drawable/ic_x_circle_darkgrey.xml | 16 +++++ 2 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 app/src/main/res/drawable/ic_x_circle_darkgrey.xml diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt index 6307dd2a..30e2d6c7 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt @@ -1,8 +1,8 @@ package com.texthip.thip.ui.common.forms import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedTextField @@ -13,7 +13,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource @@ -21,20 +20,23 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.texthip.thip.R +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 BorderedTextField( modifier: Modifier = Modifier, - hint: String + hint: String, + text: String, + onTextChange: (String) -> Unit, + onDelete: () -> Unit, ) { - var text by rememberSaveable { mutableStateOf("") } val myStyle = typography.menu_r400_s14_h24.copy(lineHeight = 14.sp) OutlinedTextField( value = text, - onValueChange = { text = it }, + onValueChange = onTextChange, placeholder = { Text( text = hint, @@ -43,7 +45,9 @@ fun BorderedTextField( ) }, textStyle = myStyle, - modifier = modifier.size(width = 320.dp, height = 48.dp), + modifier = modifier + .fillMaxWidth() + .height(48.dp), shape = RoundedCornerShape(12.dp), colors = TextFieldDefaults.colors( focusedTextColor = colors.White, @@ -55,32 +59,36 @@ fun BorderedTextField( ), trailingIcon = { - if (text.isNotEmpty()) { - Icon( - painter = painterResource(id = R.drawable.ic_x_circle_white), - contentDescription = "Clear text", - modifier = Modifier.clickable { text = "" }, - tint = Color.Unspecified - ) - } else { - Icon( - painter = painterResource(id = R.drawable.ic_x_circle), - contentDescription = "Clear text" - ) - } + Icon( + painter = painterResource( + if (text.isEmpty()) R.drawable.ic_x_circle_darkgrey + else R.drawable.ic_x_circle_grey + ), + contentDescription = "Clear", + modifier = Modifier.clickable { + onDelete() + }, + tint = Color.Unspecified + ) } ) } @Composable -@Preview(showBackground = true, backgroundColor = 0xFF000000, widthDp = 360, heightDp = 200) +@Preview() fun BorderedTextFieldPreview() { - Box( - modifier = Modifier.size(width = 360.dp, height = 200.dp), - contentAlignment = Alignment.Center - ) { + ThipTheme { + var text by rememberSaveable { mutableStateOf("") } + BorderedTextField( - hint = "κ°€μ΄λ“œ ν…μŠ€νŠΈλ₯Ό μž…λ ₯" + hint = "κ°€μ΄λ“œ ν…μŠ€νŠΈλ₯Ό μž…λ ₯", + text = text, + onTextChange = { newText -> + text = newText + }, + onDelete = { + text = "" + }, ) } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_x_circle_darkgrey.xml b/app/src/main/res/drawable/ic_x_circle_darkgrey.xml new file mode 100644 index 00000000..01013a94 --- /dev/null +++ b/app/src/main/res/drawable/ic_x_circle_darkgrey.xml @@ -0,0 +1,16 @@ + + + + From d161fc05fd8d0fc2bfabf1727d1339d5d9898fc8 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:42:13 +0900 Subject: [PATCH 12/22] =?UTF-8?q?[refactor]:=20bordered=20text=20field=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=EA=B3=BC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/forms/BorderedTextField.kt | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt index 30e2d6c7..7a6cc930 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt @@ -1,6 +1,8 @@ package com.texthip.thip.ui.common.forms import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsFocusedAsState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.shape.RoundedCornerShape @@ -11,6 +13,7 @@ import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier @@ -29,10 +32,32 @@ fun BorderedTextField( modifier: Modifier = Modifier, hint: String, text: String, + canRemove: Boolean = true, onTextChange: (String) -> Unit, onDelete: () -> Unit, + onRemoveField: () -> Unit ) { val myStyle = typography.menu_r400_s14_h24.copy(lineHeight = 14.sp) + val interactionSource = remember { MutableInteractionSource() } + val isFocused by interactionSource.collectIsFocusedAsState() + + val iconRes = when { + isFocused && text.isEmpty() -> R.drawable.ic_x_circle_darkgrey + isFocused && text.isNotEmpty() -> R.drawable.ic_x_circle_grey + !isFocused && canRemove -> R.drawable.ic_delete + else -> null + } + + val iconEnabled = when (iconRes) { + R.drawable.ic_x_circle_grey -> true + R.drawable.ic_delete -> true + else -> false + } + + val iconTint = when (iconRes) { + R.drawable.ic_delete -> colors.Grey02 + else -> Color.Unspecified + } OutlinedTextField( value = text, @@ -49,28 +74,32 @@ fun BorderedTextField( .fillMaxWidth() .height(48.dp), shape = RoundedCornerShape(12.dp), + interactionSource = interactionSource, colors = TextFieldDefaults.colors( focusedTextColor = colors.White, + unfocusedTextColor = colors.White, focusedIndicatorColor = colors.Grey02, unfocusedIndicatorColor = colors.Grey02, focusedContainerColor = colors.Black00, unfocusedContainerColor = colors.Black00, cursorColor = colors.NeonGreen, ), - trailingIcon = { - Icon( - painter = painterResource( - if (text.isEmpty()) R.drawable.ic_x_circle_darkgrey - else R.drawable.ic_x_circle_grey - ), - contentDescription = "Clear", - modifier = Modifier.clickable { - onDelete() - }, - tint = Color.Unspecified - ) - } + iconRes?.let { + Icon( + painter = painterResource(id = it), + contentDescription = "Delete or Clear", + modifier = Modifier.clickable(enabled = iconEnabled) { + when (it) { + R.drawable.ic_x_circle_grey -> onDelete() + R.drawable.ic_delete -> onRemoveField() + } + }, + tint = iconTint + ) + } + }, + singleLine = true ) } @@ -89,6 +118,9 @@ fun BorderedTextFieldPreview() { onDelete = { text = "" }, + onRemoveField = { + // ν•„λ“œ 제거 + }, ) } } \ No newline at end of file From 31d87f3cd7486c8f6f4ff74b9280f625d22ee9f8 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:54:57 +0900 Subject: [PATCH 13/22] =?UTF-8?q?[refactor]:=20bordered=20text=20field=20f?= =?UTF-8?q?ocus=EB=90=90=EC=9D=84=20=EB=95=8C=20=ED=85=8C=EB=91=90?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=B5=EC=96=B4=EC=A7=80=EB=8A=94=EA=B1=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/common/forms/BorderedTextField.kt | 95 +++++++++++-------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt b/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt index 7a6cc930..c9157d1e 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/forms/BorderedTextField.kt @@ -1,23 +1,28 @@ package com.texthip.thip.ui.common.forms +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsFocusedAsState +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text -import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -56,51 +61,61 @@ fun BorderedTextField( val iconTint = when (iconRes) { R.drawable.ic_delete -> colors.Grey02 + else -> Color.Unspecified } - OutlinedTextField( - value = text, - onValueChange = onTextChange, - placeholder = { - Text( - text = hint, - color = colors.Grey02, - style = myStyle - ) - }, - textStyle = myStyle, + Box( modifier = modifier .fillMaxWidth() - .height(48.dp), - shape = RoundedCornerShape(12.dp), - interactionSource = interactionSource, - colors = TextFieldDefaults.colors( - focusedTextColor = colors.White, - unfocusedTextColor = colors.White, - focusedIndicatorColor = colors.Grey02, - unfocusedIndicatorColor = colors.Grey02, - focusedContainerColor = colors.Black00, - unfocusedContainerColor = colors.Black00, - cursorColor = colors.NeonGreen, - ), - trailingIcon = { - iconRes?.let { - Icon( - painter = painterResource(id = it), - contentDescription = "Delete or Clear", - modifier = Modifier.clickable(enabled = iconEnabled) { - when (it) { - R.drawable.ic_x_circle_grey -> onDelete() - R.drawable.ic_delete -> onRemoveField() + .height(48.dp) + .border(width = 1.dp, color = colors.Grey02, shape = RoundedCornerShape(12.dp)), + ) { + BasicTextField( + value = text, + onValueChange = onTextChange, + textStyle = myStyle.copy(color = colors.White), + singleLine = true, + modifier = Modifier + .fillMaxWidth() + .matchParentSize() + .padding(horizontal = 12.dp, vertical = 14.dp), + interactionSource = interactionSource, + cursorBrush = SolidColor(colors.NeonGreen), + decorationBox = { innerTextField -> + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Box(modifier = Modifier.weight(1f)) { + if (text.isEmpty()) { + Text( + text = hint, + color = colors.Grey02, + style = myStyle + ) } - }, - tint = iconTint - ) + innerTextField() + } + + iconRes?.let { + Icon( + painter = painterResource(id = it), + contentDescription = "Action Icon", + modifier = Modifier + .clickable(enabled = iconEnabled) { + when (it) { + R.drawable.ic_x_circle_grey -> onDelete() + R.drawable.ic_delete -> onRemoveField() + } + }, + tint = iconTint + ) + } + } } - }, - singleLine = true - ) + ) + } } @Composable From b3f42408ff0f120d1c47bb5673aa38ee1283287c Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:55:26 +0900 Subject: [PATCH 14/22] =?UTF-8?q?[UI]:=20=ED=88=AC=ED=91=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B6=80=EB=B6=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=83=9D=EC=84=B1=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group/note/component/VoteInputSection.kt | 119 ++++++++++++++++++ app/src/main/res/values/strings.xml | 3 + 2 files changed, 122 insertions(+) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt new file mode 100644 index 00000000..c3bae78d --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt @@ -0,0 +1,119 @@ +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.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.SolidColor +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.BorderedTextField +import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.ui.theme.ThipTheme.typography + +@Composable +fun VoteInputSection( + title: String, + onTitleChange: (String) -> Unit, + options: List, + onOptionChange: (index: Int, newText: String) -> Unit, + onAddOption: () -> Unit, + onRemoveOption: (index: Int) -> Unit, + modifier: Modifier = Modifier, + maxOptionLength: Int = 20, + maxOptions: Int = 5 +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + BasicTextField( + value = title, + onValueChange = { if (it.length <= maxOptionLength) onTitleChange(it) }, + textStyle = typography.smalltitle_m500_s18_h24.copy(color = colors.White), + modifier = Modifier + .fillMaxWidth(), + cursorBrush = SolidColor(colors.NeonGreen), + decorationBox = { innerTextField -> + if (title.isEmpty()) { + Text( + text = stringResource(R.string.vote_title_placeholder), + color = colors.Grey02, + style = typography.smalltitle_m500_s18_h24 + ) + } + innerTextField() + } + ) + + options.forEachIndexed { index, option -> + val canRemove = index >= 2 // 3번째 ν•­λͺ©λΆ€ν„° μ‚­μ œ κ°€λŠ₯ + BorderedTextField( + text = option, + onTextChange = { + if (it.length <= maxOptionLength) onOptionChange(index, it) + }, + onDelete = { onOptionChange(index, "") }, // x λ²„νŠΌ 클릭 μ‹œ λ‚΄μš© μ‚­μ œ + onRemoveField = { if (canRemove) onRemoveOption(index) }, // μ“°λ ˆκΈ°ν†΅ 클릭 μ‹œ ν•­λͺ© 제거 + canRemove = canRemove, + hint = stringResource(R.string.vote_content_placeholder) + ) + } + + if (options.size < maxOptions) { + Button( + onClick = onAddOption, + modifier = Modifier + .fillMaxWidth() + .height(44.dp), + shape = RoundedCornerShape(12.dp), + colors = ButtonDefaults.buttonColors( + containerColor = colors.White, + ), + ) { + Text( + text = stringResource(R.string.add_content), + style = typography.smalltitle_sb600_s16_h24, + color = colors.Black + ) + } + } + } +} + +@Preview +@Composable +private fun VoteInputSectionPreview() { + var title by rememberSaveable { mutableStateOf("") } + var options by rememberSaveable { mutableStateOf(mutableListOf("", "")) } + + VoteInputSection( + title = title, + onTitleChange = { title = it }, + options = options, + onOptionChange = { index, newText -> + options = options.toMutableList().also { it[index] = newText } + }, + onAddOption = { + if (options.size < 5) { + options = options.toMutableList().also { it.add("") } + } + }, + onRemoveOption = { index -> + options = options.toMutableList().also { it.removeAt(index) } + } + ) +} \ 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 da5dac49..0a48e622 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -168,6 +168,9 @@ μ „μ²΄νŽ˜μ΄μ§€λ₯Ό μ΄ˆκ³Όν•  수 μ—†μ–΄μš”. μ§€κΈˆ 읽은 κ·Έ λΆ€λΆ„, μ–΄λ• λ‚˜μš”? ...ν•œ 생각이 λ“€μ—ˆμ–΄μš”.πŸ€” + νˆ¬ν‘œ λ‚΄μš©μ„ 20자 μ΄λ‚΄λ‘œ μž…λ ₯ν•˜μ„Έμš”. + ν•­λͺ©μ„ 20자 μ΄λ‚΄λ‘œ μž…λ ₯ + ν•­λͺ© μΆ”κ°€ ν”Όλ“œ From 536e669c666607b33e98e2e5aed614a7e693517f Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 17 Jul 2025 15:56:56 +0900 Subject: [PATCH 15/22] =?UTF-8?q?[UI]:=20focus=20=ED=95=B4=EC=A0=9C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group/note/component/VoteInputSection.kt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt index c3bae78d..6c780861 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteInputSection.kt @@ -1,5 +1,7 @@ package com.texthip.thip.ui.group.note.component +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth @@ -12,10 +14,12 @@ 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.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -36,8 +40,16 @@ fun VoteInputSection( maxOptionLength: Int = 20, maxOptions: Int = 5 ) { + val focusManager = LocalFocusManager.current + Column( - modifier = modifier, + modifier = modifier + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { + focusManager.clearFocus() // λ°”κΉ₯ 클릭 μ‹œ 포컀슀 ν•΄μ œ + }, verticalArrangement = Arrangement.spacedBy(16.dp) ) { BasicTextField( @@ -75,7 +87,10 @@ fun VoteInputSection( if (options.size < maxOptions) { Button( - onClick = onAddOption, + onClick = { + focusManager.clearFocus() // ν•­λͺ© μΆ”κ°€ μ‹œ 포컀슀 ν•΄μ œ + onAddOption() + }, modifier = Modifier .fillMaxWidth() .height(44.dp), From 1cc9795e964673634d11f9266f228b1ebc35c6ef Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 17 Jul 2025 16:29:37 +0900 Subject: [PATCH 16/22] =?UTF-8?q?[UI]:=20tooltip=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../texthip/thip/ui/common/modal/ToolTip.kt | 19 ++++++++++--------- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/modal/ToolTip.kt b/app/src/main/java/com/texthip/thip/ui/common/modal/ToolTip.kt index 183acbc1..dd292125 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/modal/ToolTip.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/modal/ToolTip.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -19,6 +18,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -27,7 +27,6 @@ import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography -import androidx.compose.ui.platform.LocalDensity enum class ArrowPosition { LEFT, CENTER, RIGHT @@ -57,6 +56,7 @@ fun PopupModal( text: String, modifier: Modifier = Modifier, arrowPosition: ArrowPosition = ArrowPosition.RIGHT, + isEligible: Boolean = true, onClose: () -> Unit = {} ) { Column( @@ -70,14 +70,14 @@ fun PopupModal( val arrowModifier = when (arrowPosition) { ArrowPosition.LEFT -> Modifier .align(Alignment.TopStart) - .padding(start = 24.dp) + .padding(start = 64.dp) ArrowPosition.CENTER -> Modifier .align(Alignment.TopCenter) ArrowPosition.RIGHT -> Modifier .align(Alignment.TopEnd) - .padding(end = 24.dp) + .padding(end = 64.dp) } TriangleArrow( color = colors.DarkGrey, @@ -95,7 +95,7 @@ fun PopupModal( ) { Text( text = text, - color = colors.NeonGreen, + color = if (isEligible) colors.NeonGreen else colors.Red, style = typography.info_m500_s12, modifier = Modifier.weight(1f) ) @@ -117,25 +117,26 @@ fun PopupModal( private fun PopupPrev() { Column { PopupModal( - text = stringResource(R.string.condition_of_general_review,80), + text = stringResource(R.string.condition_of_general_review), modifier = Modifier .width(400.dp) .padding(16.dp), arrowPosition = ArrowPosition.LEFT ) PopupModal( - text = stringResource(R.string.condition_of_general_review,80), + text = stringResource(R.string.condition_of_general_review), modifier = Modifier .width(400.dp) .padding(16.dp), arrowPosition = ArrowPosition.CENTER ) PopupModal( - text = stringResource(R.string.condition_of_general_review,80), + text = stringResource(R.string.condition_of_general_review), modifier = Modifier .width(400.dp) .padding(16.dp), - arrowPosition = ArrowPosition.RIGHT + arrowPosition = ArrowPosition.RIGHT, + isEligible = false ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0a48e622..6e4f731c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,7 +11,7 @@ %dμ‹œκ°„ μ „ - λ…μ„œμ§„ν–‰λ„ %d%%λΆ€ν„° 총평을 μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + λ…μ„œ 진행도 80%λ₯Ό 달성해야 총평을 μž‘μ„±ν•  수 μžˆμ–΄μš”. λŒ“κΈ€ μž‘μ„±μ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. λ³΄λŸ¬κ°€κΈ° μ†Œκ°œ From 3f5993d7163d5e8203eb306c73bf15d3b770d904 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Thu, 17 Jul 2025 16:30:19 +0900 Subject: [PATCH 17/22] =?UTF-8?q?[UI]:=20=ED=88=AC=ED=91=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=99=94=EB=A9=B4=20=EC=99=84=EB=A3=8C=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../group/note/component/PageInputSection.kt | 16 ++- .../note/screen/GroupVoteCreateScreen.kt | 117 ++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt index 748b68a3..9e527e4e 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt @@ -1,11 +1,13 @@ package com.texthip.thip.ui.group.note.component +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -15,6 +17,8 @@ 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.layout.LayoutCoordinates +import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -32,7 +36,9 @@ fun PageInputSection( onPageTextChange: (String) -> Unit, isGeneralReview: Boolean, onGeneralReviewToggle: (Boolean) -> Unit, - bookTotalPage: Int + bookTotalPage: Int, + onInfoClick: () -> Unit, + onInfoPositionCaptured: (LayoutCoordinates) -> Unit ) { val allRangeText = stringResource(R.string.all_range) @@ -73,6 +79,12 @@ fun PageInputSection( Icon( painter = painterResource(R.drawable.ic_information), contentDescription = null, + modifier = Modifier + .size(20.dp) + .onGloballyPositioned { coordinates -> + onInfoPositionCaptured(coordinates) + } + .clickable { onInfoClick() }, tint = colors.Grey02 ) @@ -107,5 +119,7 @@ private fun PageInputSectionPreview() { isGeneralReview = isGeneralReview, onGeneralReviewToggle = { isGeneralReview = it }, bookTotalPage = 500, + onInfoClick = {}, + onInfoPositionCaptured = {} ) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt new file mode 100644 index 00000000..4efe1f48 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt @@ -0,0 +1,117 @@ +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.absoluteOffset +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.LayoutCoordinates +import androidx.compose.ui.layout.positionInRoot +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 +import androidx.compose.ui.zIndex +import com.texthip.thip.R +import com.texthip.thip.ui.common.modal.ArrowPosition +import com.texthip.thip.ui.common.modal.PopupModal +import com.texthip.thip.ui.common.topappbar.InputTopAppBar +import com.texthip.thip.ui.group.note.component.PageInputSection +import com.texthip.thip.ui.group.note.component.VoteInputSection +import com.texthip.thip.ui.theme.ThipTheme + +@Composable +fun GroupVoteCreateScreen() { + var pageText by rememberSaveable { mutableStateOf("") } + var isGeneralReview by rememberSaveable { mutableStateOf(false) } + + var title by rememberSaveable { mutableStateOf("") } + var options by rememberSaveable { mutableStateOf(mutableListOf("", "")) } + + val density = LocalDensity.current + var showTooltip by rememberSaveable { mutableStateOf(true) } + + // Tooltip μœ„μΉ˜ μΈ‘μ •μš© state + val iconCoordinates = remember { mutableStateOf(null) } + + Box(modifier = Modifier.fillMaxSize()) { + Column { + InputTopAppBar( + title = stringResource(R.string.create_vote), + isRightButtonEnabled = false, + onLeftClick = { /* λ’€λ‘œκ°€κΈ° λ™μž‘ */ }, + onRightClick = { /* μ™„λ£Œ λ™μž‘ */ } + ) + + Column( + modifier = Modifier + .padding(vertical = 32.dp, horizontal = 20.dp), + verticalArrangement = Arrangement.spacedBy(32.dp), + ) { + PageInputSection( + pageText = pageText, + onPageTextChange = { pageText = it }, + isGeneralReview = isGeneralReview, + onGeneralReviewToggle = { isGeneralReview = it }, + bookTotalPage = 600, + onInfoClick = { showTooltip = true }, + onInfoPositionCaptured = { iconCoordinates.value = it } + ) + + VoteInputSection( + title = title, + onTitleChange = { title = it }, + options = options, + onOptionChange = { index, newText -> + options = options.toMutableList().also { it[index] = newText } + }, + onAddOption = { + if (options.size < 5) { + options = options.toMutableList().also { it.add("") } + } + }, + onRemoveOption = { index -> + options = options.toMutableList().also { it.removeAt(index) } + } + ) + } + } + + + if (showTooltip && iconCoordinates.value != null) { + val yOffsetDp = with(density) { + iconCoordinates.value!!.positionInRoot().y.toDp() + 32.dp + } + + Box( + modifier = Modifier + .absoluteOffset(y = yOffsetDp) + .padding(horizontal = 20.dp) + .zIndex(1f) + ) { + PopupModal( + text = stringResource(R.string.condition_of_general_review), + arrowPosition = ArrowPosition.RIGHT, + isEligible = false, + onClose = { showTooltip = false } + ) + } + } + } +} + +@Preview +@Composable +private fun GroupVoteCreateScreenPreview() { + ThipTheme { + GroupVoteCreateScreen() + } +} \ No newline at end of file From a5401d3d0c52e9df15285b54757a6bd820a769f8 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Sat, 19 Jul 2025 00:21:39 +0900 Subject: [PATCH 18/22] =?UTF-8?q?[refactor]:=20=EC=B4=9D=ED=8F=89=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EA=B0=80=EB=8A=A5=ED=95=A0=EB=95=8C?= =?UTF-8?q?=EB=A7=8C=20toggle=20button=20enabled=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/common/buttons/ToggleSwitchButton.kt | 7 ++ .../group/note/component/PageInputSection.kt | 5 +- .../note/screen/GroupNoteCreateScreen.kt | 88 ++++++++++++++----- .../note/screen/GroupVoteCreateScreen.kt | 7 +- 4 files changed, 81 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt index 624889e5..4e3f8c07 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/ToggleSwitchButton.kt @@ -23,6 +23,7 @@ import com.texthip.thip.ui.theme.ThipTheme.colors @Composable fun ToggleSwitchButton( isChecked: Boolean, + enabled: Boolean = true, onToggleChange: (Boolean) -> Unit ) { Switch( @@ -31,11 +32,17 @@ fun ToggleSwitchButton( onCheckedChange = onToggleChange, colors = SwitchDefaults.colors( checkedThumbColor = colors.White, + disabledCheckedThumbColor = colors.White, checkedTrackColor = colors.Purple, + disabledCheckedTrackColor = colors.Purple, uncheckedThumbColor = colors.White, + disabledUncheckedThumbColor = colors.White, uncheckedTrackColor = colors.DarkGrey, + disabledUncheckedTrackColor = colors.DarkGrey, uncheckedBorderColor = Color.Transparent, + disabledUncheckedBorderColor = Color.Transparent, ), + enabled = enabled, thumbContent = { Icon( painter = painterResource(R.drawable.ic_circle), diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt index 9e527e4e..752580fb 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/PageInputSection.kt @@ -37,6 +37,7 @@ fun PageInputSection( isGeneralReview: Boolean, onGeneralReviewToggle: (Boolean) -> Unit, bookTotalPage: Int, + isEligible: Boolean, onInfoClick: () -> Unit, onInfoPositionCaptured: (LayoutCoordinates) -> Unit ) { @@ -100,7 +101,8 @@ fun PageInputSection( onToggleChange = { checked -> onGeneralReviewToggle(checked) onPageTextChange(if (checked) allRangeText else "") - } + }, + enabled = isEligible ) } } @@ -119,6 +121,7 @@ private fun PageInputSectionPreview() { isGeneralReview = isGeneralReview, onGeneralReviewToggle = { isGeneralReview = it }, bookTotalPage = 500, + isEligible = true, onInfoClick = {}, onInfoPositionCaptured = {} ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt index c918a95d..7c96a263 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -1,19 +1,28 @@ 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.absoluteOffset import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.LayoutCoordinates +import androidx.compose.ui.layout.positionInRoot +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 +import androidx.compose.ui.zIndex import com.texthip.thip.R +import com.texthip.thip.ui.common.modal.ArrowPosition +import com.texthip.thip.ui.common.modal.PopupModal import com.texthip.thip.ui.common.topappbar.InputTopAppBar import com.texthip.thip.ui.group.note.component.OpinionInputSection import com.texthip.thip.ui.group.note.component.PageInputSection @@ -27,36 +36,69 @@ fun GroupNoteCreateScreen() { val isFormFilled = pageText.isNotBlank() && opinionText.isNotBlank() - Column( + val density = LocalDensity.current + var showTooltip by rememberSaveable { mutableStateOf(false) } + + // Tooltip μœ„μΉ˜ μΈ‘μ •μš© state + val iconCoordinates = remember { mutableStateOf(null) } + + var isEligible by rememberSaveable { mutableStateOf(false) } // TODO: μ„œλ²„ 데이터? + + Box( modifier = Modifier.fillMaxSize() ) { - InputTopAppBar( - title = stringResource(R.string.write_record), - isRightButtonEnabled = isFormFilled, - onLeftClick = { /* λ’€λ‘œκ°€κΈ° λ™μž‘ */ }, - onRightClick = { /* μ™„λ£Œ λ™μž‘ */ } - ) - - Column( - modifier = Modifier - .padding(vertical = 32.dp, horizontal = 20.dp), - verticalArrangement = Arrangement.spacedBy(32.dp), - ) { - PageInputSection( - pageText = pageText, - onPageTextChange = { pageText = it }, - isGeneralReview = isGeneralReview, - onGeneralReviewToggle = { isGeneralReview = it }, - bookTotalPage = 500 // TODO: μ„œλ²„ λ°μ΄ν„°λ‘œ λ³€κ²½ + Column { + InputTopAppBar( + title = stringResource(R.string.write_record), + isRightButtonEnabled = isFormFilled, + onLeftClick = { /* λ’€λ‘œκ°€κΈ° λ™μž‘ */ }, + onRightClick = { /* μ™„λ£Œ λ™μž‘ */ } ) - OpinionInputSection( - text = opinionText, - onTextChange = { opinionText = it } - ) + Column( + modifier = Modifier + .padding(vertical = 32.dp, horizontal = 20.dp), + verticalArrangement = Arrangement.spacedBy(32.dp), + ) { + PageInputSection( + pageText = pageText, + onPageTextChange = { pageText = it }, + isGeneralReview = isGeneralReview, + onGeneralReviewToggle = { isGeneralReview = it }, + isEligible = isEligible, + bookTotalPage = 600, + onInfoClick = { showTooltip = true }, + onInfoPositionCaptured = { iconCoordinates.value = it } + ) + OpinionInputSection( + text = opinionText, + onTextChange = { opinionText = it } + ) + + } + } + if (showTooltip && iconCoordinates.value != null) { + val yOffsetDp = with(density) { + iconCoordinates.value!!.positionInRoot().y.toDp() + 32.dp + } + + Box( + modifier = Modifier + .absoluteOffset(y = yOffsetDp) + .padding(horizontal = 20.dp) + .zIndex(1f) + ) { + PopupModal( + text = stringResource(R.string.condition_of_general_review), + arrowPosition = ArrowPosition.RIGHT, + isEligible = false, + onClose = { showTooltip = false } + ) + } } } + } @Preview diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt index 4efe1f48..3cbc87bc 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt @@ -37,11 +37,13 @@ fun GroupVoteCreateScreen() { var options by rememberSaveable { mutableStateOf(mutableListOf("", "")) } val density = LocalDensity.current - var showTooltip by rememberSaveable { mutableStateOf(true) } + var showTooltip by rememberSaveable { mutableStateOf(false) } // Tooltip μœ„μΉ˜ μΈ‘μ •μš© state val iconCoordinates = remember { mutableStateOf(null) } + var isEligible by rememberSaveable { mutableStateOf(false) } // TODO: μ„œλ²„ 데이터? + Box(modifier = Modifier.fillMaxSize()) { Column { InputTopAppBar( @@ -61,6 +63,7 @@ fun GroupVoteCreateScreen() { onPageTextChange = { pageText = it }, isGeneralReview = isGeneralReview, onGeneralReviewToggle = { isGeneralReview = it }, + isEligible = isEligible, bookTotalPage = 600, onInfoClick = { showTooltip = true }, onInfoPositionCaptured = { iconCoordinates.value = it } @@ -100,7 +103,7 @@ fun GroupVoteCreateScreen() { PopupModal( text = stringResource(R.string.condition_of_general_review), arrowPosition = ArrowPosition.RIGHT, - isEligible = false, + isEligible = isEligible, onClose = { showTooltip = false } ) } From 8b340b823bdb6f1fe33a20ccf1e6872d6e197379 Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Sat, 19 Jul 2025 00:32:17 +0900 Subject: [PATCH 19/22] =?UTF-8?q?[chore]:=20=EC=82=AD=EC=A0=9C=ED=95=9C=20?= =?UTF-8?q?string=20=EB=90=98=EB=8F=8C=EB=A6=AC=EA=B8=B0=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c88e1feb..1b87df01 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -125,6 +125,7 @@ μ°Έμ—¬ "%1$sλ‹˜μ˜ 진행도 " λͺ¨μž„λ°© μ°Έμ—¬ν•  μ‚¬λžŒ! + / %1$sλͺ… %1$s %1$s일 λ‚¨μŒ μ°Έμ—¬ν•˜κΈ° From 23b0e10b52f6a7668a56b37015c514433447f09e Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Sat, 19 Jul 2025 00:35:40 +0900 Subject: [PATCH 20/22] =?UTF-8?q?[UI]:=20=ED=88=AC=ED=91=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=99=94=EB=A9=B4=20=EC=99=84=EB=A3=8C=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=B6=94=EA=B0=80=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/group/note/screen/GroupVoteCreateScreen.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt index 3cbc87bc..96c182b2 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt @@ -44,11 +44,18 @@ fun GroupVoteCreateScreen() { var isEligible by rememberSaveable { mutableStateOf(false) } // TODO: μ„œλ²„ 데이터? + // μ™„λ£Œ λ²„νŠΌ ν™œμ„±ν™” 쑰건 + val filledOptionsCount = options.count { it.isNotBlank() } + val isRightButtonEnabled = + (isGeneralReview || pageText.isNotBlank()) && + title.isNotBlank() && + filledOptionsCount >= 2 + Box(modifier = Modifier.fillMaxSize()) { Column { InputTopAppBar( title = stringResource(R.string.create_vote), - isRightButtonEnabled = false, + isRightButtonEnabled = isRightButtonEnabled, onLeftClick = { /* λ’€λ‘œκ°€κΈ° λ™μž‘ */ }, onRightClick = { /* μ™„λ£Œ λ™μž‘ */ } ) From d5e5a891833cbadccc53562752f7927b4e9651df Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Sat, 19 Jul 2025 00:40:37 +0900 Subject: [PATCH 21/22] =?UTF-8?q?[fix]:=20=ED=88=AC=ED=91=9C=20=ED=95=AD?= =?UTF-8?q?=EB=AA=A9=20=EC=88=98=EC=A0=95=20=EC=95=88=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/group/note/screen/GroupVoteCreateScreen.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt index 96c182b2..f3b3953d 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupVoteCreateScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable @@ -34,7 +35,7 @@ fun GroupVoteCreateScreen() { var isGeneralReview by rememberSaveable { mutableStateOf(false) } var title by rememberSaveable { mutableStateOf("") } - var options by rememberSaveable { mutableStateOf(mutableListOf("", "")) } + val options = remember { mutableStateListOf("", "") } val density = LocalDensity.current var showTooltip by rememberSaveable { mutableStateOf(false) } @@ -81,15 +82,15 @@ fun GroupVoteCreateScreen() { onTitleChange = { title = it }, options = options, onOptionChange = { index, newText -> - options = options.toMutableList().also { it[index] = newText } + options[index] = newText }, onAddOption = { if (options.size < 5) { - options = options.toMutableList().also { it.add("") } + options.add("") } }, onRemoveOption = { index -> - options = options.toMutableList().also { it.removeAt(index) } + options.removeAt(index) } ) } From 01c17d5ffc338bb2ac7ca7a2f85263c87588290d Mon Sep 17 00:00:00 2001 From: Naeun Kim <102296721+Nico1eKim@users.noreply.github.com> Date: Sat, 19 Jul 2025 00:44:44 +0900 Subject: [PATCH 22/22] =?UTF-8?q?[fix]:=20=EC=B4=9D=ED=8F=89=20toast=20mes?= =?UTF-8?q?sage=20=EC=83=89=EC=83=81=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20?= =?UTF-8?q?=EB=9C=A8=EA=B2=8C=20=EC=88=98=EC=A0=95=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/ui/group/note/screen/GroupNoteCreateScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt index 7c96a263..083c01c5 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/screen/GroupNoteCreateScreen.kt @@ -42,7 +42,7 @@ fun GroupNoteCreateScreen() { // Tooltip μœ„μΉ˜ μΈ‘μ •μš© state val iconCoordinates = remember { mutableStateOf(null) } - var isEligible by rememberSaveable { mutableStateOf(false) } // TODO: μ„œλ²„ 데이터? + var isEligible by rememberSaveable { mutableStateOf(true) } // TODO: μ„œλ²„ 데이터? Box( modifier = Modifier.fillMaxSize() @@ -92,7 +92,7 @@ fun GroupNoteCreateScreen() { PopupModal( text = stringResource(R.string.condition_of_general_review), arrowPosition = ArrowPosition.RIGHT, - isEligible = false, + isEligible = isEligible, onClose = { showTooltip = false } ) }