Samir Basnet
03/20/2021, 6:58 AMSamir Basnet
03/20/2021, 7:24 AM@HiltViewModel
class UserViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() {
var login = mutableStateOf("")
var password = mutableStateOf("")
val loginState: MutableState<ApiState<LoginResponse>> = mutableStateOf(ApiState.Empty)
fun onLoginChange(login: String) {
this.login.value = login
}
fun onPasswordChange(password: String) {
this.password.value = password
}
fun resetLogin(){
this.login.value = ""
this.password.value = ""
this.loginState.value = ApiState.Empty
}
fun loginUser() {
viewModelScope.launch {
loginState.value = ApiState.Loading
loginState.value = userRepository.callLoginApi(LoginParams(login.value, password.value))
}
}
}
@ExperimentalComposeUiApi
@ExperimentalAnimationApi
@Composable
fun LoginScreen(navController: NavController, viewModel: UserViewModel) {
val loginState = viewModel.loginState.value
var startAnimation by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
delay(5)
if (!startAnimation)
startAnimation = true
}
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
painter = painterResource(id = R.drawable.gradient_background),
contentDescription = null,
)
AnimatedVisibility(
visible = startAnimation,
enter = slideInVertically(animationSpec = TweenSpec(durationMillis = 900))
) {
Card(
modifier = Modifier
.padding(horizontal = 15.dp, vertical = 20.dp)
.fillMaxWidth()
.wrapContentHeight(),
) {
Column(
modifier = Modifier.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
MahalSectionHeader(
modifier = Modifier
.padding(top = 20.dp, start = 15.dp)
.align(Alignment.Start), label = "LOGIN"
)
LoginFields(viewModel)
ForgotAndLoginButtons(
modifier = Modifier
.align(Alignment.End)
.padding(end = 15.dp),
loginState,
viewModel
)
NoAccountSection(
modifier = Modifier.align(Alignment.CenterHorizontally),
navController = navController
)
SocialLoginSection(navController)
Spacer(modifier = Modifier.padding(bottom = 20.dp))
}
}
}
MahalErrorSnackBar(apiState = loginState, modifier = Modifier.align(Alignment.TopCenter))
if (loginState is ApiState.Success) {
viewModel.resetLogin()
navController.navigate("home")
}
}
}
@ExperimentalAnimationApi
@Composable
private fun ForgotAndLoginButtons(
modifier: Modifier,
loginState: ApiState<LoginResponse>,
viewModel: UserViewModel,
) {
MahalTextButton(
modifier = modifier,
label = "Forgot password?",
performAction = { })
MahalSolidButton(label = "Login", apiState = loginState) {
viewModel.loginUser()
}
}
@ExperimentalComposeUiApi
@Composable
private fun LoginFields(viewModel: UserViewModel) {
val passwordFocusRequester = remember { FocusRequester() }
val focusManager = LocalFocusManager.current
val autofill = LocalAutofill.current
var numberMode by remember { mutableStateOf(false) }
MahalFirstTextField(
input = viewModel.login,
label = if (numberMode) "Mobile Number" else "Email",
keyboardType = if (numberMode) KeyboardType.Phone else KeyboardType.Email,
leadingIcon = if (numberMode) Icons.Filled.Phone else Icons.Filled.Email,
nextFocusRequester = passwordFocusRequester,
autofill = autofill,
) {
if (it == "4321")
numberMode = !numberMode
viewModel.onLoginChange(it)
}
MahalPasswordField(
label = "Password",
imeAction = ImeAction.Done,
focusRequester = passwordFocusRequester,
focusManager = focusManager,
autofill = autofill
) {
viewModel.onPasswordChange(it)
}
}
Samir Basnet
03/20/2021, 7:25 AM