diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 0c0c33838..2f0367c47 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt b/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt index 648f7036a..e2da0bd70 100644 --- a/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt +++ b/app/src/main/java/com/wap/wapp/navigation/WappNavHost.kt @@ -77,7 +77,11 @@ fun WappNavHost( navigateToSignUp = navController::navigateToSignUp, ) signUpScreen( - navigateToNotice = navController::navigateToNotice, + navigateToNotice = { + navController.navigateToNotice( + navOptions { popUpTo(navController.graph.id) { inclusive = true } }, + ) + }, navigateToSignIn = navController::navigateToSignIn, ) noticeScreen() diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepository.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepository.kt index 00e51ac84..ac988f856 100644 --- a/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepository.kt +++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepository.kt @@ -6,4 +6,6 @@ interface AuthRepository { suspend fun deleteUser(): Result suspend fun isUserSignIn(): Result + + suspend fun checkMemberCode(code: String): Result } diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepositoryImpl.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepositoryImpl.kt index 3e855fcb2..d79a21bab 100644 --- a/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepositoryImpl.kt +++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/auth/AuthRepositoryImpl.kt @@ -11,4 +11,7 @@ class AuthRepositoryImpl @Inject constructor( override suspend fun deleteUser(): Result = authDataSource.deleteUser() override suspend fun isUserSignIn(): Result = authDataSource.isUserSignIn() + + override suspend fun checkMemberCode(code: String): Result = + authDataSource.checkMemberCode(code) } diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepository.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepository.kt index 7d7cec07b..8c6141546 100644 --- a/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepository.kt +++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepository.kt @@ -5,7 +5,7 @@ interface ManagementRepository { suspend fun postManager(userId: String): Result - suspend fun getManagementCode(code: String): Result + suspend fun checkManagementCode(code: String): Result suspend fun deleteManager(userId: String): Result } diff --git a/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepositoryImpl.kt b/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepositoryImpl.kt index eb7d4b328..440ae1566 100644 --- a/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepositoryImpl.kt +++ b/core/data/src/main/java/com/wap/wapp/core/data/repository/management/ManagementRepositoryImpl.kt @@ -12,8 +12,8 @@ class ManagementRepositoryImpl @Inject constructor( override suspend fun postManager(userId: String): Result = managementDataSource.postManager(userId) - override suspend fun getManagementCode(code: String): Result = - managementDataSource.getManagementCode(code) + override suspend fun checkManagementCode(code: String): Result = + managementDataSource.checkManagementCode(code) override suspend fun deleteManager(userId: String): Result = managementDataSource.deleteManager(userId) diff --git a/core/designsystem/src/main/java/com/wap/designsystem/component/Button.kt b/core/designsystem/src/main/java/com/wap/designsystem/component/Button.kt index 4d65350d5..367bb75c3 100644 --- a/core/designsystem/src/main/java/com/wap/designsystem/component/Button.kt +++ b/core/designsystem/src/main/java/com/wap/designsystem/component/Button.kt @@ -28,7 +28,7 @@ fun WappButton( onClick = { onClick() }, enabled = isEnabled, colors = ButtonDefaults.buttonColors( - contentColor = WappTheme.colors.black, + contentColor = WappTheme.colors.white, containerColor = WappTheme.colors.yellow34, disabledContentColor = WappTheme.colors.white, disabledContainerColor = WappTheme.colors.grayA2, diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/CheckMemberCodeUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/CheckMemberCodeUseCase.kt new file mode 100644 index 000000000..0dcf0d647 --- /dev/null +++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/auth/CheckMemberCodeUseCase.kt @@ -0,0 +1,21 @@ +package com.wap.wapp.core.domain.usecase.auth + +import com.wap.wapp.core.data.repository.auth.AuthRepository +import com.wap.wapp.core.domain.model.CodeValidation +import javax.inject.Inject + +class CheckMemberCodeUseCase @Inject constructor( + private val authRepository: AuthRepository, +) { + suspend operator fun invoke(code: String): Result = runCatching { + authRepository.checkMemberCode(code).fold( + onSuccess = { isValid -> + if (isValid) { + return@fold CodeValidation.VALID + } + CodeValidation.INVALID + }, + onFailure = { CodeValidation.INVALID }, + ) + } +} diff --git a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/management/ValidateManagementCodeUseCase.kt b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/management/CheckManagementCodeUseCase.kt similarity index 89% rename from core/domain/src/main/java/com/wap/wapp/core/domain/usecase/management/ValidateManagementCodeUseCase.kt rename to core/domain/src/main/java/com/wap/wapp/core/domain/usecase/management/CheckManagementCodeUseCase.kt index d9a52fcb9..999cdd644 100644 --- a/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/management/ValidateManagementCodeUseCase.kt +++ b/core/domain/src/main/java/com/wap/wapp/core/domain/usecase/management/CheckManagementCodeUseCase.kt @@ -7,12 +7,12 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class ValidateManagementCodeUseCase @Inject constructor( +class CheckManagementCodeUseCase @Inject constructor( private val managementRepository: ManagementRepository, private val userRepository: UserRepository, ) { suspend operator fun invoke(code: String): Result = runCatching { - managementRepository.getManagementCode(code) + managementRepository.checkManagementCode(code) .onSuccess { isValid -> if (isValid.not()) { // 코드가 틀렸을 경우 return@runCatching CodeValidation.INVALID diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSource.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSource.kt index 9e859b0ed..06bd34157 100644 --- a/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSource.kt +++ b/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSource.kt @@ -6,4 +6,6 @@ interface AuthDataSource { suspend fun deleteUser(): Result suspend fun isUserSignIn(): Result + + suspend fun checkMemberCode(code: String): Result } diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSourceImpl.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSourceImpl.kt index 5b4489edf..84def2902 100644 --- a/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSourceImpl.kt +++ b/core/network/src/main/java/com/wap/wapp/core/network/source/auth/AuthDataSourceImpl.kt @@ -2,6 +2,8 @@ package com.wap.wapp.core.network.source.auth import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseAuth.AuthStateListener +import com.google.firebase.firestore.FirebaseFirestore +import com.wap.wapp.core.network.constant.CODES_COLLECTION import com.wap.wapp.core.network.utils.await import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.suspendCancellableCoroutine @@ -9,6 +11,7 @@ import javax.inject.Inject class AuthDataSourceImpl @Inject constructor( private val firebaseAuth: FirebaseAuth, + private val firebaseFirestore: FirebaseFirestore, ) : AuthDataSource { override suspend fun signOut(): Result = runCatching { firebaseAuth.signOut() @@ -45,4 +48,13 @@ class AuthDataSourceImpl @Inject constructor( } } } + + override suspend fun checkMemberCode(code: String): Result = runCatching { + val result = firebaseFirestore.collection(CODES_COLLECTION) + .whereEqualTo("user", code) + .get() + .await() + + result.isEmpty.not() + } } diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSource.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSource.kt index 210825677..866f164b1 100644 --- a/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSource.kt +++ b/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSource.kt @@ -5,7 +5,7 @@ interface ManagementDataSource { suspend fun postManager(userId: String): Result - suspend fun getManagementCode(code: String): Result + suspend fun checkManagementCode(code: String): Result suspend fun deleteManager(userId: String): Result } diff --git a/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSourceImpl.kt b/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSourceImpl.kt index 9437382d3..feb8599ef 100644 --- a/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSourceImpl.kt +++ b/core/network/src/main/java/com/wap/wapp/core/network/source/management/ManagementDataSourceImpl.kt @@ -29,7 +29,7 @@ class ManagementDataSourceImpl @Inject constructor( .await() } - override suspend fun getManagementCode(code: String): Result = runCatching { + override suspend fun checkManagementCode(code: String): Result = runCatching { val result = firebaseFirestore.collection(CODES_COLLECTION) .whereEqualTo("management", code) .get() diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt index d03e9fa1d..1ed34624f 100644 --- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInContent.kt @@ -32,12 +32,13 @@ import com.wap.wapp.feature.auth.R.string internal fun SignInContent( openSignInSheet: () -> Unit, navigateToNotice: () -> Unit, + modifier: Modifier = Modifier, ) { val scrollState = rememberScrollState() Column( verticalArrangement = Arrangement.Center, - modifier = Modifier + modifier = modifier .fillMaxSize() .padding(horizontal = 16.dp) .verticalScroll(scrollState), diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt index 107fc75ec..53c87c39b 100644 --- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signin/SignInScreen.kt @@ -196,6 +196,7 @@ internal fun SignInScreen( } }, navigateToNotice = { navigateToNotice() }, + modifier = Modifier.addFocusCleaner(focusManager), ) } } diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt index 1d4efd890..4be640d33 100644 --- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpScreen.kt @@ -22,7 +22,10 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState +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.ExperimentalComposeUiApi import androidx.compose.ui.Modifier @@ -34,6 +37,7 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.wap.designsystem.WappTheme import com.wap.designsystem.component.WappSubTopBar import com.wap.designsystem.modifier.addFocusCleaner @@ -43,6 +47,7 @@ import com.wap.wapp.feature.auth.R.drawable.ic_card import com.wap.wapp.feature.auth.R.drawable.ic_door import com.wap.wapp.feature.auth.R.string import com.wap.wapp.feature.auth.signup.SignUpViewModel.SignUpEvent +import com.wap.wapp.feature.auth.signup.validation.CodeValidationDialog import kotlinx.coroutines.flow.collectLatest @Composable @@ -68,11 +73,18 @@ internal fun SignUpScreen( val snackBarHostState = remember { SnackbarHostState() } val keyboardController = LocalSoftwareKeyboardController.current val focusManager = LocalFocusManager.current + var showCodeValidationDialog by remember { mutableStateOf(false) } LaunchedEffect(true) { viewModel.signUpEventFlow.collectLatest { when (it) { - is SignUpEvent.Success -> navigateToNotice() + is SignUpEvent.SignUpSuccess -> navigateToNotice() + + is SignUpEvent.ValidateUserInformationSuccess -> { + showCodeValidationDialog = true + } + + is SignUpEvent.CheckMemberCodeSuccess -> viewModel.postUserProfile() is SignUpEvent.Failure -> snackBarHostState.showSnackbar(message = it.throwable.toSupportingText()) @@ -92,6 +104,20 @@ internal fun SignUpScreen( .addFocusCleaner(focusManager) .padding(paddingValue), ) { + if (showCodeValidationDialog) { + CodeValidationDialog( + code = viewModel.memberCode.collectAsStateWithLifecycle().value, + setValidationCode = viewModel::setWapMemberCode, + onConfirmRequest = viewModel::checkMemberCode, + onDismissRequest = { showCodeValidationDialog = false }, + isError = viewModel.isError.collectAsStateWithLifecycle().value, + supportingText = + stringResource( + viewModel.errorSupportingText.collectAsStateWithLifecycle().value, + ), + ) + } + WappSubTopBar( modifier = Modifier .fillMaxWidth() @@ -189,7 +215,7 @@ internal fun SignUpScreen( Spacer(modifier = Modifier.weight(1f)) Button( - onClick = { viewModel.postUserProfile() }, + onClick = { viewModel.validateUserInformation() }, modifier = Modifier .fillMaxWidth() .height(48.dp), diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt index bafb9840c..5f29039e7 100644 --- a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/SignUpViewModel.kt @@ -2,36 +2,51 @@ package com.wap.wapp.feature.auth.signup import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.wap.wapp.core.domain.model.CodeValidation +import com.wap.wapp.core.domain.usecase.auth.CheckMemberCodeUseCase import com.wap.wapp.core.domain.usecase.user.PostUserProfileUseCase +import com.wap.wapp.feature.auth.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class SignUpViewModel @Inject constructor( private val postUserProfileUseCase: PostUserProfileUseCase, + private val checkMemberCodeUseCase: CheckMemberCodeUseCase, ) : ViewModel() { - private val _signUpEventFlow = MutableSharedFlow() - val signUpEventFlow: SharedFlow get() = _signUpEventFlow + val signUpEventFlow: SharedFlow = _signUpEventFlow.asSharedFlow() private val _signUpName: MutableStateFlow = MutableStateFlow("") - val signUpName: StateFlow get() = _signUpName + val signUpName: StateFlow = _signUpName.asStateFlow() private val _signUpStudentId: MutableStateFlow = MutableStateFlow("") - val signUpStudentId: StateFlow get() = _signUpStudentId + val signUpStudentId: StateFlow = _signUpStudentId.asStateFlow() private val _signUpYear: MutableStateFlow = MutableStateFlow("") - val signUpYear: StateFlow get() = _signUpYear + val signUpYear: StateFlow = _signUpYear.asStateFlow() private val _signUpSemester: MutableStateFlow = MutableStateFlow(FIRST_SEMESTER) - val signUpSemester: StateFlow get() = _signUpSemester + val signUpSemester: StateFlow = _signUpSemester.asStateFlow() + + private val _memberCode: MutableStateFlow = MutableStateFlow("") + val memberCode: StateFlow = _memberCode.asStateFlow() + + private val _isError: MutableStateFlow = MutableStateFlow(false) + val isError: StateFlow get() = _isError - fun postUserProfile() = viewModelScope.launch { + private val _errorSupportingText: MutableStateFlow = + MutableStateFlow(R.string.sign_up_dialog_hint) + val errorSupportingText: StateFlow = _errorSupportingText.asStateFlow() + + fun validateUserInformation() = viewModelScope.launch { if (!isValidStudentId()) { _signUpEventFlow.emit( SignUpEvent.Failure(IllegalStateException("학번은 9자리로만 입력하실 수 있어요!")), @@ -39,17 +54,37 @@ class SignUpViewModel @Inject constructor( return@launch } - postUserProfileUseCase( - userName = _signUpName.value, - studentId = _signUpStudentId.value, - registeredAt = "${_signUpYear.value} ${_signUpSemester.value}", - ).onSuccess { - _signUpEventFlow.emit(SignUpEvent.Success) + _signUpEventFlow.emit(SignUpEvent.ValidateUserInformationSuccess) + } + + fun checkMemberCode() = viewModelScope.launch { + checkMemberCodeUseCase(_memberCode.value).onSuccess { + when (it) { + CodeValidation.VALID -> + _signUpEventFlow.emit(SignUpEvent.CheckMemberCodeSuccess) + + CodeValidation.INVALID -> { + _isError.value = true + _errorSupportingText.value = R.string.sign_up_incorrect_code + } + } }.onFailure { throwable -> + _isError.value = true _signUpEventFlow.emit(SignUpEvent.Failure(throwable)) } } + suspend fun postUserProfile() = postUserProfileUseCase( + userName = _signUpName.value, + studentId = _signUpStudentId.value, + registeredAt = "${_signUpYear.value} ${_signUpSemester.value}", + ).onSuccess { + _signUpEventFlow.emit(SignUpEvent.SignUpSuccess) + }.onFailure { throwable -> + _signUpEventFlow.emit(SignUpEvent.Failure(throwable)) + _isError.value = true + } + fun isValidStudentId(): Boolean = (_signUpStudentId.value.length == STUDENT_ID_LENGTH) fun setName(name: String) { _signUpName.value = name } @@ -60,8 +95,12 @@ class SignUpViewModel @Inject constructor( fun setSemester(semester: String) { _signUpSemester.value = semester } + fun setWapMemberCode(code: String) { _memberCode.value = code } + sealed class SignUpEvent { - data object Success : SignUpEvent() + data object ValidateUserInformationSuccess : SignUpEvent() + data object CheckMemberCodeSuccess : SignUpEvent() + data object SignUpSuccess : SignUpEvent() data class Failure(val throwable: Throwable) : SignUpEvent() } diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/navigation/SignInNavigation.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/navigation/SignUpNavigation.kt similarity index 100% rename from feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/navigation/SignInNavigation.kt rename to feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/navigation/SignUpNavigation.kt diff --git a/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/CodeValidationDialog.kt b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/CodeValidationDialog.kt new file mode 100644 index 000000000..944503817 --- /dev/null +++ b/feature/auth/src/main/java/com/wap/wapp/feature/auth/signup/validation/CodeValidationDialog.kt @@ -0,0 +1,91 @@ +package com.wap.wapp.feature.auth.signup.validation + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +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.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +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.feature.auth.R + +@Composable +internal fun CodeValidationDialog( + code: String, + isError: Boolean, + supportingText: String, + setValidationCode: (String) -> Unit, + onConfirmRequest: () -> Unit, + onDismissRequest: () -> Unit, +) { + val focusManager = LocalFocusManager.current + + Dialog( + onDismissRequest = onDismissRequest, + properties = DialogProperties( + usePlatformDefaultWidth = false, + ), + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .wrapContentHeight() + .fillMaxWidth() + .padding(horizontal = 30.dp, vertical = 20.dp) + .addFocusCleaner(focusManager) + .clip(RoundedCornerShape(10.dp)) + .background(WappTheme.colors.black25), + ) { + Text( + text = stringResource(R.string.sign_up_dialog_title), + style = WappTheme.typography.titleBold, + color = WappTheme.colors.white, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 20.dp), + ) + + Text( + text = stringResource(R.string.sign_up_dialog_content), + style = WappTheme.typography.captionMedium, + color = WappTheme.colors.white, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 10.dp), + ) + + Spacer(modifier = Modifier.padding(vertical = 10.dp)) + + WappTextField( + value = code, + onValueChanged = setValidationCode, + label = R.string.code, + isError = isError, + supportingText = supportingText, + ) + + Spacer(modifier = Modifier.padding(vertical = 10.dp)) + + WappButton( + onClick = onConfirmRequest, + isEnabled = code.isNotBlank(), + modifier = Modifier + .fillMaxWidth() + .padding(20.dp), + ) + } + } +} diff --git a/feature/auth/src/main/res/values/strings.xml b/feature/auth/src/main/res/values/strings.xml index 4ae4b1039..c696054e2 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 : WAP + 잘못된 코드입니다. + code 1학기 2학기 완료 diff --git a/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationScreen.kt b/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationScreen.kt index 7184b20a9..9f70cdcaf 100644 --- a/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationScreen.kt +++ b/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationScreen.kt @@ -93,7 +93,7 @@ fun ManagementValidationScreen( Spacer(modifier = Modifier.padding(vertical = 8.dp)) WappButton( - onClick = { viewModel.validateManagementCode() }, + onClick = { viewModel.checkManagementCode() }, isEnabled = code.isNotBlank(), modifier = Modifier.padding(horizontal = 32.dp), ) diff --git a/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationViewModel.kt b/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationViewModel.kt index 02a880556..77551333f 100644 --- a/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationViewModel.kt +++ b/feature/management/src/main/java/com/wap/wapp/feature/management/validation/ManagementValidationViewModel.kt @@ -3,7 +3,7 @@ package com.wap.wapp.feature.management.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.core.domain.usecase.management.CheckManagementCodeUseCase import com.wap.wapp.feature.management.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -13,7 +13,7 @@ import javax.inject.Inject @HiltViewModel class ManagementValidationViewModel @Inject constructor( - private val validateManagementCodeUseCase: ValidateManagementCodeUseCase, + private val checkManagementCodeUseCase: CheckManagementCodeUseCase, ) : ViewModel() { private val _managementCodeUiState: MutableStateFlow = MutableStateFlow(ManagementCodeUiState.Init) @@ -30,30 +30,26 @@ class ManagementValidationViewModel @Inject constructor( MutableStateFlow(R.string.management_dialog_hint) val errorSupportingText: StateFlow get() = _errorSupportingText - fun validateManagementCode() { - viewModelScope.launch { - validateManagementCodeUseCase(_managementCode.value) - .onSuccess { - when (it) { - CodeValidation.VALID -> { - _managementCodeUiState.value = ManagementCodeUiState.Success - } - - CodeValidation.INVALID -> { - _isError.value = true - _errorSupportingText.value = R.string.management_incorrect_code - } + fun checkManagementCode() = viewModelScope.launch { + checkManagementCodeUseCase(_managementCode.value) + .onSuccess { + when (it) { + CodeValidation.VALID -> { + _managementCodeUiState.value = ManagementCodeUiState.Success + } + + CodeValidation.INVALID -> { + _isError.value = true + _errorSupportingText.value = R.string.management_incorrect_code } } - .onFailure { throwable -> - _managementCodeUiState.value = ManagementCodeUiState.Failure(throwable) - } - } + } + .onFailure { throwable -> + _managementCodeUiState.value = ManagementCodeUiState.Failure(throwable) + } } - fun setManagementCode(code: String) { - _managementCode.value = code - } + fun setManagementCode(code: String) { _managementCode.value = code } sealed class ManagementCodeUiState { data object Init : ManagementCodeUiState()