If anyone have implemented a login api in compose ...
# compose
s
If anyone have implemented a login api in compose screen with viewModel can you please share a gist. I am a little confused about how to do it properly
Copy code
@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)
    }
}
For now just consider when i press back i come back to LoginScreen with a reset. Above is how i have done. Please guide me what can be improved