Skip to content

Commit

Permalink
Merge pull request #37 from YAPP-Github/feature/tgyuu/PC-388
Browse files Browse the repository at this point in the history
[PC-388] 프로필 등록 모듈 추가 및 TextInput Component 추가
  • Loading branch information
tgyuuAn authored Jan 17, 2025
2 parents 9a66c42 + ed817c3 commit ce8d5aa
Show file tree
Hide file tree
Showing 33 changed files with 838 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
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.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
Expand All @@ -17,32 +21,39 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.puzzle.designsystem.R
import com.puzzle.designsystem.foundation.PieceTheme

@Composable
fun PieceTextInputFields(
fun PieceTextInputDefault(
value: String,
onValueChange: (String) -> Unit,
@DrawableRes imageId: Int,
onImageClick: () -> Unit,
modifier: Modifier = Modifier,
placeholder: String = "",
onDone: () -> Unit = {},
hint: String = "",
readOnly: Boolean = false,
keyboardType: KeyboardType = KeyboardType.Text,
throttleTime: Long = 2000L,
onDone: () -> Unit = {},
) {
val keyboardController = LocalSoftwareKeyboardController.current
var lastDoneTime by remember { mutableLongStateOf(0L) }
Expand All @@ -51,6 +62,7 @@ fun PieceTextInputFields(
value = value,
onValueChange = onValueChange,
singleLine = true,
readOnly = readOnly,
keyboardOptions = KeyboardOptions(
keyboardType = keyboardType,
imeAction = ImeAction.Done
Expand All @@ -71,7 +83,7 @@ fun PieceTextInputFields(
Box {
if (value.isEmpty()) {
Text(
text = placeholder,
text = hint,
style = PieceTheme.typography.bodyMM,
color = PieceTheme.colors.dark3,
modifier = Modifier.align(Alignment.CenterStart)
Expand All @@ -95,24 +107,263 @@ fun PieceTextInputFields(
modifier = modifier
.height(52.dp)
.clip(RoundedCornerShape(8.dp))
.background(PieceTheme.colors.light3)
.background(
if (readOnly) PieceTheme.colors.light2
else PieceTheme.colors.light3
)
.padding(horizontal = 16.dp, vertical = 14.dp),
)
}

@Composable
fun PieceTextInputLong(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
hint: String = "",
limit: Int? = null,
readOnly: Boolean = false,
keyboardType: KeyboardType = KeyboardType.Text,
throttleTime: Long = 2000L,
onDone: () -> Unit = {},
) {
val keyboardController = LocalSoftwareKeyboardController.current
var lastDoneTime by remember { mutableLongStateOf(0L) }
var isFocused by remember { mutableStateOf(false) }

BasicTextField(
value = value,
onValueChange = { input ->
limit?.let { if (input.length <= limit) onValueChange(input) } ?: onValueChange(input)
},
singleLine = true,
readOnly = readOnly,
keyboardOptions = KeyboardOptions(
keyboardType = keyboardType,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = {
val currentTime = System.currentTimeMillis()
if (currentTime - lastDoneTime >= throttleTime) {
keyboardController?.hide()
onDone()
lastDoneTime = currentTime
}
}
),
textStyle = PieceTheme.typography.bodyMM,
cursorBrush = SolidColor(PieceTheme.colors.primaryDefault),
decorationBox = { innerTextField ->
Box {
if (value.isEmpty()) {
Text(
text = hint,
style = PieceTheme.typography.bodyMM,
color = PieceTheme.colors.dark3,
modifier = Modifier.align(Alignment.CenterStart)
)
}

innerTextField()

if (limit != null && isFocused && value.isNotEmpty()) {
Text(
text = buildAnnotatedString {
withStyle(style = SpanStyle(color = PieceTheme.colors.primaryDefault)) {
append(value.length.toString())
}
append("/${limit}")
},
style = PieceTheme.typography.bodySM,
modifier = Modifier.align(Alignment.BottomEnd),
)
}
}
},
modifier = modifier
.onFocusChanged { focusState -> isFocused = focusState.isFocused }
.heightIn(min = 160.dp)
.clip(RoundedCornerShape(8.dp))
.background(
if (readOnly) PieceTheme.colors.light2
else PieceTheme.colors.light3
)
.padding(horizontal = 16.dp, vertical = 14.dp),
)
}

@Composable
fun PieceTextInputAI(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
throttleTime: Long = 2000L,
onDone: () -> Unit = {},
) {
val keyboardController = LocalSoftwareKeyboardController.current
var lastDoneTime by remember { mutableLongStateOf(0L) }
var isFocused by remember { mutableStateOf(false) }

BasicTextField(
value = value,
onValueChange = onValueChange,
singleLine = true,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(
onDone = {
val currentTime = System.currentTimeMillis()
if (currentTime - lastDoneTime >= throttleTime) {
keyboardController?.hide()
onDone()
lastDoneTime = currentTime
}
}
),
textStyle = PieceTheme.typography.bodyMM,
cursorBrush = SolidColor(PieceTheme.colors.primaryDefault),
decorationBox = { innerTextField ->
Box {
if (value.isEmpty()) {
Text(
text = "작성해주신 내용을 AI가 요약하고 있어요",
style = PieceTheme.typography.bodyMM,
color = PieceTheme.colors.dark3,
modifier = Modifier.align(Alignment.CenterStart)
)
}

innerTextField()

val imageRes = if (value.isEmpty()) R.drawable.ic_textinput_3dots
else if (isFocused) R.drawable.ic_textinput_check
else R.drawable.ic_textinput_pencil

Image(
painter = painterResource(imageRes),
contentDescription = null,
modifier = Modifier
.size(24.dp)
.align(Alignment.CenterEnd),
)
}
},
modifier = modifier
.onFocusChanged { focusState -> isFocused = focusState.isFocused }
.height(52.dp)
.clip(RoundedCornerShape(8.dp))
.background(PieceTheme.colors.primaryLight)
.padding(horizontal = 16.dp, vertical = 14.dp),
)
}

@Composable
fun PieceTextInputDropDown(
value: String,
modifier: Modifier = Modifier,
hint: String = "",
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.height(52.dp)
.clip(RoundedCornerShape(8.dp))
.background(PieceTheme.colors.light3)
.padding(horizontal = 16.dp, vertical = 14.dp),
) {
Text(
text = value.ifEmpty { hint },
style = PieceTheme.typography.bodyMM,
color = if (value.isNotEmpty()) PieceTheme.colors.black
else PieceTheme.colors.dark2,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(1f),
)

Image(
painter = painterResource(R.drawable.ic_textinput_dropdown),
contentDescription = null,
modifier = Modifier.size(24.dp),
)
}
}

@Preview
@Composable
fun PreviewPieceTextInputFields() {
private fun PreviewPieceTextInputDefault() {
PieceTheme {
PieceTextInputFields(
PieceTextInputDefault(
value = "Label",
onValueChange = {},
placeholder = "hint",
hint = "hint",
imageId = R.drawable.ic_alarm,
onImageClick = {},
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)
}
}
}

@Preview
@Composable
private fun PreviewPieceTextInputLong() {
PieceTheme {
PieceTextInputLong(
value = "Label",
onValueChange = {},
limit = 6,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)
}
}

@Preview
@Composable
private fun PreviewPieceTextInputAI() {
PieceTheme {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
PieceTextInputAI(
value = "",
onValueChange = {},
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)

PieceTextInputAI(
value = "Label",
onValueChange = { },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)
}
}
}

@Preview
@Composable
private fun PreviewPieceTextInputDropDown() {
PieceTheme {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
PieceTextInputDropDown(
value = "",
hint = "안내 문구",
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)

PieceTextInputDropDown(
value = "Label",
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)
}
}
}
26 changes: 26 additions & 0 deletions core/designsystem/src/main/res/drawable/ic_plus.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M18,1.5L18,1.5A16.5,16.5 0,0 1,34.5 18L34.5,18A16.5,16.5 0,0 1,18 34.5L18,34.5A16.5,16.5 0,0 1,1.5 18L1.5,18A16.5,16.5 0,0 1,18 1.5z"
android:fillColor="#6F00FB"/>
<path
android:pathData="M18,1.5L18,1.5A16.5,16.5 0,0 1,34.5 18L34.5,18A16.5,16.5 0,0 1,18 34.5L18,34.5A16.5,16.5 0,0 1,1.5 18L1.5,18A16.5,16.5 0,0 1,18 1.5z"
android:strokeWidth="3"
android:fillColor="#00000000"
android:strokeColor="#ffffff"/>
<path
android:pathData="M12,18H24"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
<path
android:pathData="M18,12L18,24"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
</vector>
13 changes: 13 additions & 0 deletions core/designsystem/src/main/res/drawable/ic_profile_default.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="120dp"
android:height="120dp"
android:viewportWidth="120"
android:viewportHeight="120">
<path
android:pathData="M60,0L60,0A60,60 0,0 1,120 60L120,60A60,60 0,0 1,60 120L60,120A60,60 0,0 1,0 60L0,60A60,60 0,0 1,60 0z"
android:fillColor="#F4F6FA"/>
<path
android:pathData="M57.48,18C51.03,18 45.8,22.9 45.8,28.95C45.8,29.85 45.91,30.71 46.12,31.54C46.53,33.12 45.5,35.04 43.88,35.04H36C31.58,35.04 28,38.62 28,43.04V50.16C28,51.79 29.92,52.81 31.5,52.41C32.33,52.19 33.19,52.08 34.09,52.08C40.14,52.08 45.04,57.31 45.04,63.76C45.04,70.22 40.14,75.45 34.09,75.45C33.19,75.45 32.33,75.33 31.5,75.12C29.92,74.71 28,75.74 28,77.37V84C28,88.42 31.58,92 36,92H42.88C44.5,92 45.53,90.08 45.12,88.5C44.91,87.67 44.8,86.81 44.8,85.91C44.8,79.86 50.03,74.96 56.48,74.96C62.93,74.96 68.16,79.86 68.16,85.91C68.16,86.81 68.05,87.67 67.84,88.5C67.43,90.08 68.46,92 70.08,92H76.96C81.38,92 84.96,88.42 84.96,84V76.37C84.96,74.74 86.88,73.71 88.46,74.12C89.29,74.33 90.15,74.45 91.05,74.45C97.1,74.45 102,69.22 102,62.76C102,56.31 97.1,51.08 91.05,51.08C90.15,51.08 89.29,51.19 88.46,51.41C86.88,51.81 84.96,50.79 84.96,49.16V43.04C84.96,38.62 81.38,35.04 76.96,35.04H71.08C69.46,35.04 68.43,33.12 68.84,31.54C69.05,30.71 69.16,29.85 69.16,28.95C69.16,22.9 63.93,18 57.48,18Z"
android:fillColor="#CBD1D9"
android:fillType="evenOdd"/>
</vector>
Loading

0 comments on commit ce8d5aa

Please sign in to comment.