-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 프로모션 코드 입력 화면 구현 #27 #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| android:width="66dp" | ||
| android:height="66dp" | ||
| android:viewportWidth="66" | ||
| android:viewportHeight="66"> | ||
| <path | ||
| android:pathData="M29.15,37.95L23.237,32.037C22.733,31.533 22.092,31.281 21.313,31.281C20.533,31.281 19.892,31.533 19.388,32.037C18.883,32.542 18.631,33.183 18.631,33.963C18.631,34.742 18.883,35.383 19.388,35.888L27.225,43.725C27.775,44.275 28.417,44.55 29.15,44.55C29.883,44.55 30.525,44.275 31.075,43.725L46.612,28.188C47.117,27.683 47.369,27.042 47.369,26.263C47.369,25.483 47.117,24.842 46.612,24.337C46.108,23.833 45.467,23.581 44.688,23.581C43.908,23.581 43.267,23.833 42.763,24.337L29.15,37.95ZM33,60.5C29.196,60.5 25.621,59.778 22.275,58.333C18.929,56.888 16.019,54.929 13.544,52.456C11.069,49.983 9.11,47.073 7.667,43.725C6.224,40.377 5.502,36.802 5.5,33C5.498,29.198 6.22,25.623 7.667,22.275C9.113,18.927 11.072,16.017 13.544,13.544C16.015,11.071 18.926,9.112 22.275,7.667C25.625,6.222 29.199,5.5 33,5.5C36.8,5.5 40.375,6.222 43.725,7.667C47.075,9.112 49.985,11.071 52.456,13.544C54.928,16.017 56.887,18.927 58.336,22.275C59.784,25.623 60.506,29.198 60.5,33C60.494,36.802 59.772,40.377 58.333,43.725C56.894,47.073 54.935,49.983 52.456,52.456C49.978,54.929 47.067,56.889 43.725,58.336C40.383,59.782 36.808,60.504 33,60.5Z" | ||
| android:fillColor="#10D266"/> | ||
| </vector> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| package com.konkuk.medicarecall.ui.feature.login.elder.screen | ||
|
|
||
| import androidx.compose.foundation.background | ||
| 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.fillMaxSize | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.layout.height | ||
| import androidx.compose.foundation.layout.imePadding | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.foundation.layout.systemBarsPadding | ||
| import androidx.compose.foundation.layout.wrapContentHeight | ||
| import androidx.compose.foundation.rememberScrollState | ||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||
| import androidx.compose.foundation.verticalScroll | ||
| import androidx.compose.material3.Icon | ||
| import androidx.compose.material3.Surface | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.draw.clip | ||
| import androidx.compose.ui.graphics.Color | ||
| import androidx.compose.ui.unit.dp | ||
| import androidx.compose.ui.window.Dialog | ||
| import androidx.compose.ui.window.DialogProperties | ||
| import androidx.lifecycle.compose.collectAsStateWithLifecycle | ||
| import com.konkuk.medicarecall.resources.Res | ||
| import com.konkuk.medicarecall.resources.ic_check_green | ||
| import com.konkuk.medicarecall.ui.common.component.CTAButton | ||
| import com.konkuk.medicarecall.ui.common.component.DefaultTextField | ||
| import com.konkuk.medicarecall.ui.feature.login.elder.viewmodel.LoginElderPromotionUiState | ||
| import com.konkuk.medicarecall.ui.feature.login.elder.viewmodel.LoginElderPromotionViewModel | ||
| import com.konkuk.medicarecall.ui.feature.login.myinfo.component.LoginBackButton | ||
| import com.konkuk.medicarecall.ui.theme.Black | ||
| import com.konkuk.medicarecall.ui.theme.G500 | ||
| import com.konkuk.medicarecall.ui.theme.MediCareCallTheme | ||
| import com.konkuk.medicarecall.ui.theme.White | ||
| import com.konkuk.medicarecall.ui.type.CTAButtonType | ||
| import org.jetbrains.compose.resources.vectorResource | ||
| import org.koin.compose.viewmodel.koinViewModel | ||
|
|
||
| @Composable | ||
| fun LoginElderPromotionScreen( | ||
| onBack: () -> Unit, | ||
| navigateToElderRegister: () -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| viewModel: LoginElderPromotionViewModel = koinViewModel(), | ||
| ) { | ||
| val uiState by viewModel.uiState.collectAsStateWithLifecycle() | ||
|
|
||
| LoginElderPromotionScreenLayout( | ||
| onBack = onBack, | ||
| navigateToElderRegister = navigateToElderRegister, | ||
| uiState = uiState, | ||
| onInputChanged = { viewModel.onPromotionCodeChange(it) }, | ||
| onConfirm = { viewModel.onConfirm() }, | ||
| onDismissRequest = { viewModel.onDismissRequest() }, | ||
| modifier = modifier, | ||
| ) | ||
| } | ||
|
|
||
| @Composable | ||
| private fun LoginElderPromotionScreenLayout( | ||
| onBack: () -> Unit, | ||
| navigateToElderRegister: () -> Unit, | ||
| uiState: LoginElderPromotionUiState, | ||
| onInputChanged: (String) -> Unit, | ||
| onConfirm: () -> Unit, | ||
| onDismissRequest: () -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| ) { | ||
| val scrollState = rememberScrollState() | ||
|
|
||
| Column( | ||
| modifier = modifier | ||
| .fillMaxSize() | ||
| .background(MediCareCallTheme.colors.bg) | ||
| .systemBarsPadding() | ||
| .imePadding() | ||
| .padding(horizontal = 20.dp), | ||
| ) { | ||
| LoginBackButton(onBack) | ||
| Column( | ||
| Modifier | ||
| .weight(1f) | ||
| .verticalScroll(scrollState), | ||
| ) { | ||
| Spacer(Modifier.height(30.dp)) | ||
| Text( | ||
| "프로모션 코드\n입력하기", | ||
| style = MediCareCallTheme.typography.B_26, | ||
| color = MediCareCallTheme.colors.black, | ||
| ) | ||
| Spacer(Modifier.height(30.dp)) | ||
| DefaultTextField( | ||
| value = uiState.inputValue, | ||
| onValueChange = onInputChanged, | ||
| placeHolder = "코드를 입력해주세요", | ||
| ) | ||
| Spacer(Modifier.height(30.dp)) | ||
| CTAButton( | ||
| if (uiState.inputValue.matches("^[A-Z0-9]{8}\$".toRegex())) CTAButtonType.GREEN | ||
| else CTAButtonType.DISABLED, | ||
| text = "확인", | ||
| onClick = { onConfirm() }, | ||
| ) | ||
|
|
||
| if (uiState.showDialog) { | ||
| Dialog( | ||
| onDismissRequest = onDismissRequest, | ||
| properties = DialogProperties( | ||
| dismissOnBackPress = true, | ||
| dismissOnClickOutside = true, | ||
| ), | ||
| ) { | ||
| Surface( | ||
| Modifier.fillMaxWidth() | ||
| .wrapContentHeight(), | ||
| shape = RoundedCornerShape(14.dp), | ||
| color = White, | ||
| ) { | ||
| Column( | ||
| Modifier.padding(20.dp).padding(top = 10.dp), | ||
| horizontalAlignment = Alignment.CenterHorizontally, | ||
| ) { | ||
| Icon( | ||
| imageVector = vectorResource(Res.drawable.ic_check_green), | ||
| contentDescription = "완료 아이콘", | ||
| tint = Color.Unspecified, | ||
| ) | ||
| Spacer(Modifier.height(15.5.dp)) | ||
| Text( | ||
| "인증되었습니다", style = MediCareCallTheme.typography.SB_18, | ||
| color = Black, | ||
| ) | ||
| Spacer(Modifier.height(20.dp)) | ||
| Box( | ||
| Modifier.fillMaxWidth() | ||
| .clip(RoundedCornerShape(14.dp)) | ||
| .background(G500) | ||
| .clickable { navigateToElderRegister() }, | ||
| contentAlignment = Alignment.Center, | ||
| ) { | ||
| Text( | ||
| "확인", color = White, style = MediCareCallTheme.typography.B_17, | ||
| modifier = Modifier.padding(vertical = 14.dp), | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.konkuk.medicarecall.ui.feature.login.elder.viewmodel | ||
|
|
||
| data class LoginElderPromotionUiState( | ||
| val inputValue: String = "", | ||
| val showDialog: Boolean = false, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package com.konkuk.medicarecall.ui.feature.login.elder.viewmodel | ||
|
|
||
| import androidx.lifecycle.ViewModel | ||
| import kotlinx.coroutines.flow.MutableStateFlow | ||
| import kotlinx.coroutines.flow.asStateFlow | ||
| import kotlinx.coroutines.flow.update | ||
| import org.koin.android.annotation.KoinViewModel | ||
|
|
||
| @KoinViewModel | ||
| class LoginElderPromotionViewModel: ViewModel() { | ||
| private val _uiState = MutableStateFlow(LoginElderPromotionUiState()) | ||
| val uiState = _uiState.asStateFlow() | ||
|
|
||
| fun onPromotionCodeChange(value: String) { | ||
| _uiState.update { it.copy(inputValue = value) } | ||
| } | ||
|
|
||
| fun onConfirm() { | ||
| // TODO: 프로모션 검증 로직 추가 | ||
| _uiState.update { it.copy(showDialog = true) } | ||
| } | ||
|
|
||
| fun onDismissRequest() { | ||
| _uiState.update { it.copy(showDialog = false) } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ import androidx.navigation.NavOptions | |
| import androidx.navigation.compose.composable | ||
| import com.konkuk.medicarecall.ui.feature.login.calltime.screen.CallTimeScreen | ||
| import com.konkuk.medicarecall.ui.feature.login.elder.screen.LoginElderMedInfoScreen | ||
| import com.konkuk.medicarecall.ui.feature.login.elder.screen.LoginElderPromotionScreen | ||
| import com.konkuk.medicarecall.ui.feature.login.elder.screen.LoginElderScreen | ||
| import com.konkuk.medicarecall.ui.feature.login.elder.viewmodel.LoginElderViewModel | ||
| import com.konkuk.medicarecall.ui.feature.login.myinfo.screen.LoginMyInfoScreen | ||
|
|
@@ -50,6 +51,10 @@ fun NavController.navigateToLoginFinish() { | |
| navigate(Route.LoginFinish) | ||
| } | ||
|
|
||
| fun NavController.navigateToLoginPromotion() { | ||
| navigate(Route.LoginPromotion) | ||
| } | ||
|
|
||
| fun NavGraphBuilder.loginNavGraph( | ||
| popBackStack: () -> Unit, | ||
| navigateToMainAfterLogin: () -> Unit, | ||
|
|
@@ -61,6 +66,7 @@ fun NavGraphBuilder.loginNavGraph( | |
| navigateToRegisterElderHealth: () -> Unit, | ||
| navigateToCareCallSetting: () -> Unit, | ||
| navigateToCareCallSettingWithPopUpTo: () -> Unit, | ||
| navigateToPromotion: () -> Unit, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: navigateToPromotion이 실제로 사용되는 곳이 있는지 확인
rg -n "navigateToPromotion" --type=kotlinRepository: Medicare-Call/Medicare-Call-KMP Length of output: 376 🏁 Script executed: cat -n composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/feature/login/navigation/LoginNavigation.kt | sed -n '50,160p'Repository: Medicare-Call/Medicare-Call-KMP Length of output: 4604 🏁 Script executed: cat -n composeApp/src/commonMain/kotlin/com/konkuk/medicarecall/ui/navigation/NavGraph.kt | sed -n '120,140p'Repository: Medicare-Call/Medicare-Call-KMP Length of output: 1477 사용되지 않는 파라미터 제거
🤖 Prompt for AI Agents |
||
| navigateToFinish: () -> Unit, | ||
| getSharedLoginInfoViewModel: @Composable (NavBackStackEntry) -> LoginInfoViewModel, | ||
| getSharedLoginElderViewModel: @Composable (NavBackStackEntry) -> LoginElderViewModel, | ||
|
|
@@ -140,4 +146,11 @@ fun NavGraphBuilder.loginNavGraph( | |
| navigateToMain = navigateToMainAfterLogin, | ||
| ) | ||
| } | ||
|
|
||
| composable<Route.LoginPromotion> { | ||
| LoginElderPromotionScreen( | ||
| onBack = popBackStack, | ||
| navigateToElderRegister = navigateToRegisterElder | ||
| ) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다이얼로그 닫기 후 네비게이션 처리
다이얼로그의 "확인" 버튼 클릭 시
navigateToElderRegister()만 호출하고onDismissRequest()를 호출하지 않습니다. 네비게이션 후에도showDialog가true로 남아있어 백스택 관련 이슈가 발생할 수 있습니다.🐛 제안된 수정
Box( Modifier.fillMaxWidth() .clip(RoundedCornerShape(14.dp)) .background(G500) - .clickable { navigateToElderRegister() }, + .clickable { + onDismissRequest() + navigateToElderRegister() + }, contentAlignment = Alignment.Center, )🤖 Prompt for AI Agents