From 262dad6b493855dc1fce6c5135c4d5db5470102f Mon Sep 17 00:00:00 2001 From: tgyuu-An Date: Tue, 27 Feb 2024 23:05:51 +0900 Subject: [PATCH] [FEATURE] #141 : SignUpValidationScreen + ViewModel --- .../validation/SignUpValidationScreen.kt | 102 ++++++++++++++++++ .../validation/SignUpValidationViewModel.kt | 63 +++++++++++ feature/auth/src/main/res/values/strings.xml | 5 + 3 files changed, 170 insertions(+) create mode 100644 feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationScreen.kt create mode 100644 feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationViewModel.kt diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationScreen.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationScreen.kt new file mode 100644 index 00000000..ce4480a5 --- /dev/null +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationScreen.kt @@ -0,0 +1,102 @@ +package com.wap.wapp.feature.auth.signup.validation + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.wap.designsystem.WappTheme +import com.wap.designsystem.component.WappButton +import com.wap.designsystem.component.WappTextField +import com.wap.designsystem.modifier.addFocusCleaner +import com.wap.wapp.core.commmon.extensions.toSupportingText +import com.wap.wapp.feature.auth.R +import kotlinx.coroutines.flow.collectLatest + +@Composable +fun SignUpValidationScreen( + viewModel: SignUpValidationViewModel = hiltViewModel(), + onValidationSuccess: () -> Unit, +) { + val code by viewModel.signUpCode.collectAsStateWithLifecycle() + val isError by viewModel.isError.collectAsStateWithLifecycle() + val errorSupportingText by viewModel.errorSupportingText.collectAsStateWithLifecycle() + val snackBarHostState = remember { SnackbarHostState() } + val focusManager = LocalFocusManager.current + + LaunchedEffect(true) { + viewModel.signUpCodeUiState.collectLatest { + when (it) { + is SignUpValidationViewModel.SignUpCodeUiState.Init -> {} + + is SignUpValidationViewModel.SignUpCodeUiState.Success -> + onValidationSuccess() + + is SignUpValidationViewModel.SignUpCodeUiState.Failure -> + snackBarHostState.showSnackbar(it.throwable.toSupportingText()) + } + } + } + + Scaffold( + containerColor = WappTheme.colors.backgroundBlack, + snackbarHost = { SnackbarHost(snackBarHostState) }, + ) { paddingValues -> + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .padding(paddingValues) + .fillMaxSize() + .addFocusCleaner(focusManager), + ) { + Text( + text = stringResource(R.string.sign_up_dialog_title), + style = WappTheme.typography.titleBold, + color = WappTheme.colors.white, + textAlign = TextAlign.Center, + ) + + Text( + text = stringResource(R.string.sign_up_dialog_content), + style = WappTheme.typography.captionMedium, + color = WappTheme.colors.white, + textAlign = TextAlign.Center, + ) + + Spacer(modifier = Modifier.padding(vertical = 8.dp)) + + WappTextField( + value = code, + onValueChanged = viewModel::setManagementCode, + label = R.string.code, + isError = isError, + supportingText = stringResource(id = errorSupportingText), + ) + + Spacer(modifier = Modifier.padding(vertical = 8.dp)) + + WappButton( + onClick = { viewModel.validateManagementCode() }, + isEnabled = code.isNotBlank(), + modifier = Modifier.padding(horizontal = 32.dp), + ) + } + } +} diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationViewModel.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationViewModel.kt new file mode 100644 index 00000000..0087e273 --- /dev/null +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/SignUpValidationViewModel.kt @@ -0,0 +1,63 @@ +package com.wap.wapp.feature.auth.signup.validation + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.wap.wapp.core.domain.model.CodeValidation +import com.wap.wapp.core.domain.usecase.management.ValidateManagementCodeUseCase +import com.wap.wapp.feature.auth.R +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SignUpValidationViewModel @Inject constructor( + private val validateManagementCodeUseCase: ValidateManagementCodeUseCase, +) : ViewModel() { + private val _signUpCodeUiState: MutableStateFlow = + MutableStateFlow(SignUpCodeUiState.Init) + val signUpCodeUiState: StateFlow = _signUpCodeUiState.asStateFlow() + + private val _signUpCode: MutableStateFlow = MutableStateFlow("") + val signUpCode: StateFlow = _signUpCode.asStateFlow() + + private val _isError: MutableStateFlow = MutableStateFlow(false) + val isError: StateFlow = _isError.asStateFlow() + + private val _errorSupportingText: MutableStateFlow = + MutableStateFlow(R.string.sign_up_dialog_hint) + val errorSupportingText: StateFlow = _errorSupportingText.asStateFlow() + + fun validateManagementCode() { + viewModelScope.launch { + validateManagementCodeUseCase(_signUpCode.value) + .onSuccess { + when (it) { + CodeValidation.VALID -> { + _signUpCodeUiState.value = SignUpCodeUiState.Success + } + + CodeValidation.INVALID -> { + _isError.value = true + _errorSupportingText.value = R.string.sign_up_incorrect_code + } + } + } + .onFailure { throwable -> + _signUpCodeUiState.value = SignUpCodeUiState.Failure(throwable) + } + } + } + + fun setManagementCode(code: String) { + _signUpCode.value = code + } + + sealed class SignUpCodeUiState { + data object Init : SignUpCodeUiState() + data object Success : SignUpCodeUiState() + data class Failure(val throwable: Throwable) : SignUpCodeUiState() + } +} diff --git a/feature/auth/src/main/res/values/strings.xml b/feature/auth/src/main/res/values/strings.xml index 4ae4b103..d5b94eac 100644 --- a/feature/auth/src/main/res/values/strings.xml +++ b/feature/auth/src/main/res/values/strings.xml @@ -27,6 +27,11 @@ 입부년도 입력 회원님의 기수 정보를 알려드릴게요! Door Icon + 회원 코드를 입력하세요 + WAP 회원만 해당 내용을 확인할 수 있어요. + Hint : WAPP + 잘못된 코드입니다. + code 1학기 2학기 완료