diff --git a/app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt b/app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt index 39c77e90..844798e7 100644 --- a/app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt +++ b/app/src/main/java/com/cherrish/android/presentation/calendar/CalendarScreen.kt @@ -77,7 +77,7 @@ private fun CalendarScreen( .fillMaxSize() .background(color = CherrishTheme.colors.gray100) .padding(paddingValues) - .padding(top = 40.dp), + .padding(top = 40.dp, bottom = 10.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(20.dp) ) { @@ -95,7 +95,9 @@ private fun CalendarScreen( procedureInfo = uiState.procedureInfoList, onProcedureClick = onEventClick, onAddProcedureClick = onAddButtonClick, - modifier = Modifier.padding(horizontal = 17.dp) + modifier = Modifier + .padding(horizontal = 17.dp) + .weight(1f) ) } } diff --git a/app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt b/app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt index e14d9766..8ed0a9e2 100644 --- a/app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt +++ b/app/src/main/java/com/cherrish/android/presentation/calendar/component/ProcedureScheduleCard.kt @@ -70,8 +70,7 @@ fun ProcedureScheduleCard( EmptyCardView( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 24.dp) - .padding(top = 50.dp, bottom = 24.dp), + .padding(horizontal = 24.dp), onClick = onAddProcedureClick ) } else { @@ -99,7 +98,8 @@ fun ProcedureScheduleCard( LazyColumn( state = listState, - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.weight(1f) ) { items( items = procedureInfo, @@ -252,11 +252,14 @@ private fun EmptyCardView( modifier = modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { + Spacer(modifier = Modifier.weight(50f)) + Image( painter = painterResource(id = R.drawable.img_calendar_empty_view), contentDescription = null, modifier = Modifier.padding(8.dp) ) + Spacer(modifier = Modifier.weight(8f)) Text( text = "오늘 예정된 일정이 없어요.", @@ -264,11 +267,13 @@ private fun EmptyCardView( style = CherrishTheme.typography.body1R14 ) - Spacer(modifier = Modifier.height(40.dp)) + Spacer(modifier = Modifier.weight(40f)) AddProcedureButton( onClick = onClick ) + + Spacer(modifier = Modifier.weight(24f)) } } diff --git a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt index 2a6911c5..60ac9bd7 100644 --- a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt +++ b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/ProcedureScreen.kt @@ -3,12 +3,18 @@ package com.cherrish.android.presentation.calendar.procedure import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -143,127 +149,157 @@ fun ProcedureScreen( BackHandler { onBackClick() } - Column( + Scaffold( modifier = modifier .fillMaxSize() .background(CherrishTheme.colors.gray0) .navigationBarsPadding() - .padding(top = 44.dp, bottom = 20.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - BackAndCloseTopAppBar( - title = uiState.title, - onBackClick = onBackClick, - onCloseClick = onCloseClick - ) - - if (uiState.showStepProgressBar) { - StepProgressBar( - totalStep = uiState.totalSteps, - currentStep = uiState.currentStepIndex, + .padding(top = 44.dp), + containerColor = CherrishTheme.colors.gray0, + bottomBar = { + CherrishButton( + text = if (uiState.step == ProcedureStep.Downtime) "완료" else "다음", + onClick = onNextClick, + enabled = uiState.isNextEnabled, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 26.dp) - .padding(top = 20.dp) + .padding(horizontal = 24.dp) + .padding(vertical = 20.dp) + .background(CherrishTheme.colors.gray0) ) } - + ) { innerPadding -> Column( modifier = Modifier - .fillMaxWidth() - .padding(top = uiState.contentTopPadding) - .weight(1f) + .fillMaxSize() + .imePadding(), + horizontalAlignment = Alignment.CenterHorizontally ) { - when (uiState.flow) { - ProcedureFlow.Entry -> { - ExistenceContent( - selectedIndex = uiState.existenceSelectedIndex, - onItemClick = onExistenceClick, + BackAndCloseTopAppBar( + title = uiState.title, + onBackClick = onBackClick, + onCloseClick = onCloseClick + ) + + Column( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + ) { + if (uiState.showStepProgressBar) { + StepProgressBar( + totalStep = uiState.totalSteps, + currentStep = uiState.currentStepIndex, modifier = Modifier + .fillMaxWidth() .padding(horizontal = 26.dp) - .padding(bottom = 10.dp) + .padding(top = 20.dp) ) } - ProcedureFlow.NoTreat, ProcedureFlow.Treat -> { - when (uiState.step) { - ProcedureStep.Category -> { - CategoryContent( - worries = uiState.worries, - selectedWorryId = uiState.selectedWorryId, - onWorryClick = onWorryClick, + Column( + modifier = Modifier.fillMaxWidth() + ) { + when (uiState.flow) { + ProcedureFlow.Entry -> { + ExistenceContent( + selectedIndex = uiState.existenceSelectedIndex, + onItemClick = onExistenceClick, modifier = Modifier + .padding(top = uiState.contentTopPadding) .padding(horizontal = 26.dp) .padding(bottom = 10.dp) ) } - ProcedureStep.RecoverySchedule -> { - RecoveryScheduleContent( - selectedIndex = uiState.recoverySelectedIndex, - onItemClick = onRecoveryOptionClick, - year = uiState.year, - month = uiState.month, - day = uiState.day, - onYearChange = onYearChange, - onMonthChange = onMonthChange, - onDayChange = onDayChange, - errorMessage = uiState.dateErrorMessage, - modifier = Modifier.padding(horizontal = 26.dp) - ) - } + ProcedureFlow.NoTreat, ProcedureFlow.Treat -> { + when (uiState.step) { + ProcedureStep.Category -> { + CategoryContent( + worries = uiState.worries, + selectedWorryId = uiState.selectedWorryId, + onWorryClick = onWorryClick, + modifier = Modifier + .padding(top = uiState.contentTopPadding) + .padding(horizontal = 26.dp) + .padding(bottom = 10.dp) + ) + } - ProcedureStep.Filtering -> { - FilteringContent( - name = uiState.selectedWorryName, - cardItems = uiState.procedureItems, - selectedCardIds = uiState.selectedProcedureCardIds, - onCardClick = onProcedureCardClick, - bottomPadding = uiState.lazyColumnBottomPadding, - modifier = Modifier.fillMaxWidth() - ) - } + ProcedureStep.RecoverySchedule -> { + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()) + ) { + RecoveryScheduleContent( + selectedIndex = uiState.recoverySelectedIndex, + onItemClick = onRecoveryOptionClick, + year = uiState.year, + month = uiState.month, + day = uiState.day, + onYearChange = onYearChange, + onMonthChange = onMonthChange, + onDayChange = onDayChange, + errorMessage = uiState.dateErrorMessage, + modifier = Modifier + .padding(top = uiState.contentTopPadding) + .padding(horizontal = 26.dp) + ) + } + } - ProcedureStep.FilteringWithSearch -> { - FilteringWithSearchContent( - cardItems = uiState.procedureItems, - selectedCardIds = uiState.selectedProcedureCardIds, - onCardClick = onProcedureCardClick, - onSearchAction = onSearchAction, - query = uiState.searchQuery, - searchedQuery = uiState.searchedQuery, - onQueryChange = onSearchableQueryChange, - bottomContentPadding = uiState.lazyColumnBottomPadding, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - ) - } + ProcedureStep.Filtering -> { + FilteringContent( + name = uiState.selectedWorryName, + cardItems = uiState.procedureItems, + selectedCardIds = uiState.selectedProcedureCardIds, + onCardClick = onProcedureCardClick, + bottomPadding = uiState.lazyColumnBottomPadding, + modifier = Modifier.fillMaxWidth() + .padding(top = uiState.contentTopPadding) + ) + } - ProcedureStep.Downtime -> { - DowntimeContent( - cardItems = uiState.selectedProcedureCardItems, - selectedCardIds = - uiState.procedureDowntimeMap.keys.toImmutableList(), - onCardClick = onDowntimeClick, - activeCardId = uiState.selectedProcedureForDowntime?.id, - isDowntimeBottomSheetVisible = uiState.showDowntimeBottomSheet, - modifier = Modifier.fillMaxWidth() - ) + ProcedureStep.FilteringWithSearch -> { + FilteringWithSearchContent( + cardItems = uiState.procedureItems, + selectedCardIds = uiState.selectedProcedureCardIds, + onCardClick = onProcedureCardClick, + onSearchAction = onSearchAction, + query = uiState.searchQuery, + searchedQuery = uiState.searchedQuery, + onQueryChange = onSearchableQueryChange, + bottomContentPadding = uiState.lazyColumnBottomPadding, + modifier = Modifier + .fillMaxWidth() + .padding(top = uiState.contentTopPadding) + .padding(horizontal = 24.dp) + ) + } + + ProcedureStep.Downtime -> { + DowntimeContent( + cardItems = uiState.selectedProcedureCardItems, + selectedCardIds = uiState.procedureDowntimeMap.keys + .toImmutableList(), + onCardClick = onDowntimeClick, + activeCardId = uiState.selectedProcedureForDowntime?.id, + isDowntimeBottomSheetVisible = uiState + .showDowntimeBottomSheet, + modifier = Modifier + .fillMaxWidth() + .padding(top = uiState.contentTopPadding) + ) + } + } } } } } + + Spacer(modifier = Modifier.height(innerPadding.calculateBottomPadding())) } - CherrishButton( - text = "다음", - onClick = onNextClick, - enabled = uiState.isNextEnabled, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .padding(top = 24.dp) - ) } SelectedProcedureBottomSheet( diff --git a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt index 1bf43f46..42b935e0 100644 --- a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt +++ b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/DowntimeBottomSheet.kt @@ -336,7 +336,11 @@ private fun DowntimeDayPicker( ) Text( - text = "보통 $minDowntimeDays-${maxDowntimeDays}일", + text = if (minDowntimeDays == 0 && maxDowntimeDays == 0) { + "보통 다운타임 0일" + } else { + "보통 $minDowntimeDays-${maxDowntimeDays}일" + }, color = CherrishTheme.colors.gray600, style = CherrishTheme.typography.title2M16 ) diff --git a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/SelectionSection.kt b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/SelectionSection.kt index fabc53d8..4e337305 100644 --- a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/SelectionSection.kt +++ b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/component/SelectionSection.kt @@ -2,12 +2,10 @@ package com.cherrish.android.presentation.calendar.procedure.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.itemsIndexed import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -44,7 +42,7 @@ fun SelectionSection( Spacer(modifier = Modifier.height(40.dp)) - ChipGrid( + ChipFlowGrid( items = items, selectedIndex = selectedIndex, onItemClick = onItemClick @@ -53,29 +51,34 @@ fun SelectionSection( } @Composable -private fun ChipGrid( +private fun ChipFlowGrid( items: ImmutableList, onItemClick: (index: Int) -> Unit, modifier: Modifier = Modifier, selectedIndex: Int? = null ) { - LazyVerticalGrid( + Column( modifier = modifier.fillMaxWidth(), - columns = GridCells.Fixed(2), - horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { - itemsIndexed( - items = items, - key = { index, item -> "$item-$index" } - ) { index, text -> - - CherrishSelectionChip( - text = text, - onClick = { onItemClick(index) }, + items.chunked(2).forEachIndexed { rowIndex, rowItems -> + Row( modifier = Modifier.fillMaxWidth(), - isSelected = selectedIndex == index - ) + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + rowItems.forEachIndexed { colIndex, text -> + val index = rowIndex * 2 + colIndex + CherrishSelectionChip( + text = text, + onClick = { onItemClick(index) }, + modifier = Modifier.weight(1f), + isSelected = selectedIndex == index + ) + } + if (rowItems.size == 1) { + Spacer(modifier = Modifier.weight(1f)) + } + } } } } diff --git a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/content/RecoveryScheduleContent.kt b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/content/RecoveryScheduleContent.kt index 0ceecf3f..328bc3cb 100644 --- a/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/content/RecoveryScheduleContent.kt +++ b/app/src/main/java/com/cherrish/android/presentation/calendar/procedure/content/RecoveryScheduleContent.kt @@ -8,6 +8,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.relocation.BringIntoViewRequester +import androidx.compose.foundation.relocation.bringIntoViewRequester import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -15,10 +17,12 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection +import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.input.pointer.PointerEventPass import androidx.compose.ui.input.pointer.changedToUp import androidx.compose.ui.input.pointer.pointerInput @@ -33,6 +37,8 @@ import com.cherrish.android.core.designsystem.component.textfield.CherrishTextFi import com.cherrish.android.core.designsystem.theme.CherrishTheme import com.cherrish.android.presentation.calendar.procedure.component.SelectionSection import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch @Composable fun RecoveryScheduleContent( @@ -47,8 +53,10 @@ fun RecoveryScheduleContent( modifier: Modifier = Modifier, errorMessage: String? = null ) { - val hasSelection = selectedIndex != null && selectedIndex >= 0 + val coroutineScope = rememberCoroutineScope() + val bringIntoViewRequester = remember { BringIntoViewRequester() } val focusManager = LocalFocusManager.current + val hasSelection = selectedIndex != null && selectedIndex >= 0 val keyboardController = LocalSoftwareKeyboardController.current Column( @@ -75,7 +83,9 @@ fun RecoveryScheduleContent( if (hasSelection) { Column( - modifier = Modifier.padding(top = 56.dp) + modifier = Modifier + .padding(top = 56.dp) + .bringIntoViewRequester(bringIntoViewRequester) ) { val sectionTitle = if (selectedIndex == 0) { "대략적인 회복 목표일을 정해볼까요?" @@ -91,6 +101,12 @@ fun RecoveryScheduleContent( onYearChange = onYearChange, onMonthChange = onMonthChange, onDayChange = onDayChange, + onFocus = { + coroutineScope.launch { + delay(100) + bringIntoViewRequester.bringIntoView() + } + }, onDone = { focusManager.clearFocus(force = true) }, onNext = { focusManager.moveFocus(focusDirection = FocusDirection.Next) } ) @@ -112,6 +128,7 @@ private fun ScheduleSettingSection( onYearChange: (String) -> Unit, onMonthChange: (String) -> Unit, onDayChange: (String) -> Unit, + onFocus: () -> Unit, onDone: () -> Unit, onNext: () -> Unit, modifier: Modifier = Modifier @@ -142,6 +159,7 @@ private fun ScheduleSettingSection( suffix = "년", placeholder = "YYYY", onValueChange = onYearChange, + onFocus = onFocus, imeAction = ImeAction.Next, onNext = onNext, modifier = Modifier.weight(1f) @@ -151,6 +169,7 @@ private fun ScheduleSettingSection( suffix = "월", placeholder = "MM", onValueChange = onMonthChange, + onFocus = onFocus, imeAction = ImeAction.Next, onNext = onNext, modifier = Modifier.weight(1f) @@ -160,6 +179,7 @@ private fun ScheduleSettingSection( suffix = "일", placeholder = "DD", onValueChange = onDayChange, + onFocus = onFocus, imeAction = ImeAction.Done, onDone = onDone, modifier = Modifier.weight(1f) @@ -174,6 +194,7 @@ private fun DateInputBasicSection( suffix: String, placeholder: String, onValueChange: (String) -> Unit, + onFocus: () -> Unit, modifier: Modifier = Modifier, imeAction: ImeAction = ImeAction.Next, onDone: () -> Unit = {}, @@ -201,8 +222,10 @@ private fun DateInputBasicSection( keyboardImeAction = imeAction, onDoneAction = onDone, onNextAction = onNext, - paddingValues = PaddingValues(horizontal = 19.dp, vertical = 8.dp), - modifier = Modifier.weight(1f) + paddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp), + modifier = Modifier + .weight(1f) + .onFocusChanged { if (it.isFocused) onFocus() } ) Text( diff --git a/app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt b/app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt index bf6ee21f..02c6407f 100644 --- a/app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt +++ b/app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt @@ -8,8 +8,11 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -36,6 +39,8 @@ import com.cherrish.android.core.designsystem.component.button.CherrishButton import com.cherrish.android.core.designsystem.component.textfield.CherrishTextField import com.cherrish.android.core.designsystem.theme.CherrishTheme import com.cherrish.android.presentation.onboarding.information.extension.AgeSuffixTransformation +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch @Composable fun OnboardingInformationRoute( @@ -80,75 +85,81 @@ private fun OnboardingInformationScreen( val focusManager = LocalFocusManager.current val keyboardController = LocalSoftwareKeyboardController.current val ageFocusRequester = remember { FocusRequester() } - var isAgeFocused by remember { mutableStateOf(false) } - Column( - modifier = modifier - .fillMaxSize() - .background(color = CherrishTheme.colors.gray0) - .addFocusCleaner(focusManager) - .padding(paddingValues = paddingValues) - ) { - Spacer(modifier = Modifier.weight(135f)) - - UserInfoHeader() - - Spacer(modifier = Modifier.weight(70f)) - - UserInfoTextField( - textFieldName = "이름", - value = username, - onValueChange = onNameChange, - placeholder = "김체리", - keyboardImeAction = ImeAction.Next, - onNextAction = { - ageFocusRequester.requestFocus() - }, - keyboardType = KeyboardType.Text, - errorText = "이름은 최대 7자까지 입력 가능합니다.", - errorCase = nameErrorCase - ) + Scaffold( + bottomBar = { + CherrishButton( + text = "다음", + onClick = onNextClick, + enabled = enabled, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp, vertical = 30.dp) + .background(CherrishTheme.colors.gray0) + .navigationBarsPadding() - Spacer(modifier = Modifier.weight(30f)) - - UserInfoTextField( - textFieldName = "나이", - value = age, - onValueChange = onAgeChange, - placeholder = "20", - keyboardImeAction = ImeAction.Done, - onDoneAction = { - keyboardController?.hide() - focusManager.clearFocus() - }, - keyboardType = KeyboardType.Number, - visualTransformation = if (isAgeFocused) { - VisualTransformation.None - } else { - AgeSuffixTransformation( - " 세" - ) - }, - errorText = "입력 가능한 최대 나이 100세를 초과했습니다.", - errorCase = ageErrorCase, - modifier = Modifier - .focusRequester(ageFocusRequester) - .onFocusChanged { state -> - isAgeFocused = state.isFocused - } - ) + ) + } + ) { innerPadding -> + Column( + modifier = modifier + .fillMaxSize() + .background(color = CherrishTheme.colors.gray0) + .addFocusCleaner(focusManager) + .padding(paddingValues = paddingValues) + .imePadding() + ) { + Spacer(modifier = Modifier.weight(135f)) + UserInfoHeader() + Spacer(modifier = Modifier.weight(70f)) - Spacer(modifier = Modifier.weight(200f)) + UserInfoTextField( + textFieldName = "이름", + value = username, + onValueChange = onNameChange, + placeholder = "김체리", + keyboardImeAction = ImeAction.Next, + onNextAction = { ageFocusRequester.requestFocus() }, + keyboardType = KeyboardType.Text, + errorText = "이름은 최대 7자까지 입력 가능합니다.", + errorCase = nameErrorCase + ) - CherrishButton( - text = "다음", - onClick = onNextClick, - enabled = enabled, - modifier = Modifier.padding(horizontal = 24.dp) - ) + Spacer(modifier = Modifier.weight(30f)) + + UserInfoTextField( + textFieldName = "나이", + value = age, + onValueChange = onAgeChange, + placeholder = "20", + keyboardImeAction = ImeAction.Done, + onDoneAction = { + keyboardController?.hide() + kotlinx.coroutines.MainScope().launch { + delay(100) + focusManager.clearFocus() + } + }, + keyboardType = KeyboardType.Number, + visualTransformation = if (isAgeFocused) { + VisualTransformation.None + } else { + AgeSuffixTransformation(" 세") + }, + errorText = "입력 가능한 최대 나이 100세를 초과했습니다.", + errorCase = ageErrorCase, + modifier = Modifier + .focusRequester(ageFocusRequester) + .onFocusChanged { state -> + isAgeFocused = state.isFocused + } + ) - Spacer(modifier = Modifier.weight(30f)) + Spacer(modifier = Modifier.weight(200f)) + + Spacer(modifier = Modifier.padding(innerPadding.calculateBottomPadding())) + } } }