Skip to content

Commit

Permalink
[feat/#10] SignIn, SignUp 스크린의 서버통신을 Coroutine 방식으로 변경합니다.
Browse files Browse the repository at this point in the history
  • Loading branch information
SYAAINN committed Dec 2, 2024
1 parent 22edaeb commit 663c08d
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 122 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package org.sopt.and.presentation.ui.auth.screen

import org.sopt.and.data.remote.model.response.UserRegistrationResponseDto
import org.sopt.and.domain.model.Token
import org.sopt.and.domain.model.UserNo

sealed class SignInState {
data object Idle : SignInState()
data object EmailEmpty : SignInState()
data object PasswordEmpty : SignInState()
data object Success : SignInState()
data object Loading : SignInState()
data class Success(val result: Token) : SignInState()
data class Failure(val errorMessage: String) : SignInState()
}

sealed class SignUpState {
data object Idle : SignUpState()
data class Success(val response: UserRegistrationResponseDto?) : SignUpState()
data object Loading : SignUpState()
data class Success(val result: UserNo) : SignUpState()
data class Failure(val errorMessage: String) : SignUpState()
}
Original file line number Diff line number Diff line change
@@ -1,106 +1,64 @@
package org.sopt.and.presentation.ui.auth.screen

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import org.sopt.and.data.remote.model.request.LoginRequestDto
import org.sopt.and.data.remote.model.request.UserRegistrationRequestDto
import org.sopt.and.data.remote.model.response.LoginResponseDto
import org.sopt.and.data.remote.model.response.UserRegistrationResponseDto
import org.sopt.and.domain.model.User
import org.sopt.and.domain.repository.AuthRepository
import org.sopt.and.domain.repository.TokenRepository
import org.sopt.and.di.ServicePool
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import javax.inject.Inject

@HiltViewModel
class AuthViewModel @Inject constructor(
private val tokenRepository: TokenRepository,
private val authRepository: AuthRepository,
) : ViewModel() {
private val authService by lazy { ServicePool.authService }

private val _signInState = MutableStateFlow<SignInState>(SignInState.Idle)
val signInState: StateFlow<SignInState> = _signInState

private val _signInUserName = MutableLiveData("")
val signInUserName: LiveData<String> = _signInUserName

private val _signInPassword = MutableLiveData("")
val signInPassword: LiveData<String> = _signInPassword
private val _token = MutableStateFlow("")
val token: StateFlow<String> = _token

private val _signUpState = MutableStateFlow<SignUpState>(SignUpState.Idle)
val signUpState: StateFlow<SignUpState> = _signUpState

private val _signUpUserName = MutableLiveData("")
val signUpUserName: LiveData<String> = _signUpUserName

private val _signUpPassword = MutableLiveData("")
val signUpPassword: LiveData<String> = _signUpPassword

private val _signUpHobby = MutableLiveData("")
val signUpHobby: LiveData<String> = _signUpHobby



fun validateSignIn(inputEmail: String, inputPassword: String) {
fun validateSignIn(username: String, password: String) {
_signInState.value = SignInState.Loading
viewModelScope.launch {
authService.login(LoginRequestDto(inputEmail, inputPassword)).enqueue(object :
Callback<LoginResponseDto> {
override fun onResponse(
call: Call<LoginResponseDto>,
response: Response<LoginResponseDto>
) {
if (response.isSuccessful) {
_signInState.value = SignInState.Success
tokenRepository.setToken(token = response.body()!!.token)
Log.d("token", tokenRepository.getToken())
} else {
_signInState.value = SignInState.Failure(response.message())
}
}

override fun onFailure(
call: Call<LoginResponseDto>,
t: Throwable
) {
_signInState.value = SignInState.Failure(t.message.toString())
val result = authRepository.login(username = username, password = password)
_signInState.value = result.fold(
onSuccess = { token ->
tokenRepository.setToken(token.token)
Log.d("token","토큰 저장 완료! 저장값은 ${token.token} 입니다.")
SignInState.Success(token)
},
onFailure = {
SignInState.Failure(it.localizedMessage ?: "에러 발생")
}
}
)
}
}

fun validateSignUp(email: String, password: String, hobby: String) {
fun validateSignUp(username: String, password: String, hobby: String) {
_signUpState.value = SignUpState.Loading
viewModelScope.launch {
authService.registerUser(UserRegistrationRequestDto(email, password, hobby))
.enqueue(object :
Callback<UserRegistrationResponseDto> {
override fun onResponse(
call: Call<UserRegistrationResponseDto>,
response: Response<UserRegistrationResponseDto>
) {
if (response.isSuccessful) {
_signUpState.value = SignUpState.Success(response.body())
} else {
_signUpState.value = SignUpState.Failure(response.message())
}
}

override fun onFailure(
call: Call<UserRegistrationResponseDto>,
t: Throwable
) {
_signUpState.value = SignUpState.Failure(t.message.toString())
}
val result = authRepository.registerUser(user = User(
username = username,
password = password,
hobby = hobby
))
_signUpState.value = result.fold(
onSuccess = {
SignUpState.Success(it)
},
onFailure = {
SignUpState.Failure(it.localizedMessage ?: "에러 발생")
}
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,36 +49,24 @@ fun SignInRoute(
navigateToSignUp: () -> Unit,
navigateToMain: () -> Unit,
) {
val context = LocalContext.current
val signInState by authViewModel.signInState.collectAsState()

val onSignInClick: (String, String) -> Unit = { email, password ->
authViewModel.validateSignIn(email, password)
when (signInState) {
is SignInState.Success -> {
showToast(context = context, message = "로그인에 성공했습니다.")
navigateToMain()
}

is SignInState.Failure -> {
showToast(context = context, message = "로그인에 실패했습니다.")
}

else -> {}
}
}

SignInScreen(
signInState = signInState,
onSignUpClick = navigateToSignUp,
onSignInClick = onSignInClick,
onSignInClick = { email, password -> authViewModel.validateSignIn(email, password) },
navigateToMain = navigateToMain
)
}

@Composable
fun SignInScreen(
signInState: SignInState,
onSignUpClick: () -> Unit,
onSignInClick: (String, String) -> Unit
onSignInClick: (String, String) -> Unit,
navigateToMain: () -> Unit,
) {
val context = LocalContext.current
var inputEmail by remember { mutableStateOf("") }
var inputPassword by remember { mutableStateOf("") }

Expand Down Expand Up @@ -139,8 +127,7 @@ fun SignInScreen(

Button(
onClick = { onSignInClick(inputEmail, inputPassword) },
modifier = Modifier
.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(Color(0xFF0F42C7))
) {
Text(
Expand Down Expand Up @@ -227,6 +214,23 @@ fun SignInScreen(
}

Spacer(modifier = Modifier.weight(1f))

when(signInState) {
is SignInState.Success -> {
showToast(
context = context,
message = "로그인에 성공했습니다."
)
navigateToMain()
}
is SignInState.Failure -> {
showToast(
context = context,
message = "아이디와 비밃번호를 다시 확인해주세요."
)
}
else -> {}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,39 +47,24 @@ fun SignUpRoute(
navigateToSignIn: () -> Unit,
navigateToBack: () -> Unit,
) {
val context = LocalContext.current
val signUpState by authViewModel.signUpState.collectAsState()

val onSignUpClick: (String, String, String) -> Unit = { username, password, hobby ->
authViewModel.validateSignUp(username, password, hobby)
when (signUpState) {
is SignUpState.Success -> {
showToast(
context = context,
message = "회원가입에 성공했습니다. 회원번호는 ${(signUpState as SignUpState.Success).response?.result?.no}입니다."
)
navigateToSignIn()
}

is SignUpState.Failure -> {
showToast(context = context, message = "회원가입에 실패하였습니다.")
}

else -> {}
}
}

SignUpScreen(
onSignUpClick = onSignUpClick,
signUpState = signUpState,
onSignUpClick = { username, password, hobby -> authViewModel.validateSignUp(username, password, hobby)},
navigateToSignIn = navigateToSignIn,
onCancelClick = navigateToBack,
)
}

@Composable
fun SignUpScreen(
signUpState: SignUpState,
onSignUpClick: (String, String, String) -> Unit,
navigateToSignIn: () -> Unit,
onCancelClick: () -> Unit,
) {
val context = LocalContext.current
var inputEmail by remember { mutableStateOf("") }
var inputPassword by remember { mutableStateOf("") }
var inputHobby by remember { mutableStateOf("") }
Expand Down Expand Up @@ -307,9 +292,7 @@ fun SignUpScreen(
modifier = Modifier
.fillMaxWidth()
.background(color = Color(0xFF0F42C7))
.clickable(
onClick = { onSignUpClick(inputEmail, inputPassword, inputHobby) }
),
.clickable(onClick = { onSignUpClick(inputEmail, inputPassword, inputHobby) }),
contentAlignment = Alignment.Center
) {
Text(
Expand All @@ -318,6 +301,23 @@ fun SignUpScreen(
color = Color.White
)
}

when(signUpState) {
is SignUpState.Success -> {
showToast(
context = context,
message = "회원가입에 성공했습니다. 유저번호는 ${signUpState.result.no}입니다."
)
navigateToSignIn()
}
is SignUpState.Failure -> {
showToast(
context = context,
message = "회원가입에 실패했습니다. 형식을 다시 확인해주세요."
)
}
else -> {}
}
}
}

Expand Down

0 comments on commit 663c08d

Please sign in to comment.