diff --git a/app/src/main/java/com/kikidan/todakun/TodakunApp.kt b/app/src/main/java/com/kikidan/todakun/TodakunApp.kt index 901d878f..2b3afbc1 100644 --- a/app/src/main/java/com/kikidan/todakun/TodakunApp.kt +++ b/app/src/main/java/com/kikidan/todakun/TodakunApp.kt @@ -145,6 +145,7 @@ fun TodakunApp( onFinish = { navigator.resetTo(TodakunRoute.Home) }, onNavigateTerm = { navigator.goBack() }, onboardingToken = OnboardingToken(route.onboardingToken), + snackbarHostState = snackbarHostState, ) } diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml index c6051eb1..f7605165 100644 --- a/core/designsystem/src/main/res/values/strings.xml +++ b/core/designsystem/src/main/res/values/strings.xml @@ -314,6 +314,8 @@ 다음 시작하기 확인 + 회원가입에 실패했어요. 잠시 후 다시 시도해주세요 + 입력한 정보를 다시 확인해주세요. 약관 동의 diff --git a/feature/auth/src/main/java/com/kikidan/auth/component/SocialLoginButton.kt b/feature/auth/src/main/java/com/kikidan/auth/component/SocialLoginButton.kt index a3a4f346..8436459e 100644 --- a/feature/auth/src/main/java/com/kikidan/auth/component/SocialLoginButton.kt +++ b/feature/auth/src/main/java/com/kikidan/auth/component/SocialLoginButton.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Text import androidx.compose.material3.ripple import androidx.compose.runtime.Composable @@ -58,6 +59,7 @@ internal fun SocialLoginButton( provider: SocialLoginProvider, onClick: () -> Unit, modifier: Modifier = Modifier, + isLoading: Boolean = false, ) { Box( modifier = @@ -74,20 +76,28 @@ internal fun SocialLoginButton( ), contentAlignment = Alignment.Center, ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - Image( - painter = painterResource(id = provider.iconRes), - contentDescription = null, + if (isLoading) { + CircularProgressIndicator( modifier = Modifier.size(20.dp), - ) - Text( - text = stringResource(id = provider.labelRes), - style = TodakunTypography.body2Medium, color = provider.contentColor, + strokeWidth = 2.dp, ) + } else { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + Image( + painter = painterResource(id = provider.iconRes), + contentDescription = null, + modifier = Modifier.size(20.dp), + ) + Text( + text = stringResource(id = provider.labelRes), + style = TodakunTypography.body2Medium, + color = provider.contentColor, + ) + } } } } diff --git a/feature/auth/src/main/java/com/kikidan/auth/screen/LoginScreen.kt b/feature/auth/src/main/java/com/kikidan/auth/screen/LoginScreen.kt index a391f07f..4e2259f7 100644 --- a/feature/auth/src/main/java/com/kikidan/auth/screen/LoginScreen.kt +++ b/feature/auth/src/main/java/com/kikidan/auth/screen/LoginScreen.kt @@ -13,6 +13,11 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +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.res.painterResource @@ -34,6 +39,10 @@ internal fun LoginScreen( modifier: Modifier = Modifier, ) { val loginEnabled = state is LoginState.Idle || state is LoginState.Failure + var loadingProvider by remember { mutableStateOf(null) } + LaunchedEffect(state) { + if (state !is LoginState.Loading) loadingProvider = null + } Box( modifier = modifier @@ -77,8 +86,12 @@ internal fun LoginScreen( SocialLoginProvider.entries.forEach { provider -> SocialLoginButton( enabled = loginEnabled, + isLoading = state is LoginState.Loading && loadingProvider == provider, provider = provider, - onClick = { onProviderClick(provider) }, + onClick = { + loadingProvider = provider + onProviderClick(provider) + }, ) } } diff --git a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt index 586058b3..db38745a 100644 --- a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt +++ b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt @@ -5,6 +5,7 @@ import android.os.Build import androidx.activity.compose.BackHandler import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -12,7 +13,9 @@ 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.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel +import com.kikidan.designsystem.R import com.kikidan.designsystem.component.wheelpicker.BirthDateState import com.kikidan.designsystem.component.wheelpicker.BirthDateWheelPicker import com.kikidan.designsystem.component.wheelpicker.SajuBirthTimeWheelPicker @@ -34,6 +37,7 @@ fun OnboardingRoute( onFinish: () -> Unit, onNavigateTerm: () -> Unit, onboardingToken: OnboardingToken, + snackbarHostState: SnackbarHostState, modifier: Modifier = Modifier, viewModel: OnboardingViewModel = hiltViewModel(), ) { @@ -48,6 +52,8 @@ fun OnboardingRoute( // 권한을 허락하지 않더라도 앱 진입 permissionHandled = true } + val signupErrorMessage = stringResource(R.string.onboarding_signup_error) + val invalidInputErrorMessage = stringResource(R.string.onboarding_invalid_input_error) viewModel.collectSideEffect { sideEffect -> when (sideEffect) { @@ -67,7 +73,13 @@ fun OnboardingRoute( } } - else -> { /* TODO 에러 처리 스낵바 또는 다이얼로그 */ } + OnboardingSideEffect.InvalidInput -> { + snackbarHostState.showSnackbar(invalidInputErrorMessage) + } + + is OnboardingSideEffect.Failure -> { + snackbarHostState.showSnackbar(signupErrorMessage) + } } }