Tugas 11 - Auth App

 Nama : Widian Sasi Disertasiani

NRP : 5025211024

Kelas : PPB D 

Materi : Membuat Aplikasi Auntetikasi


Github: Code

Yt: Demo




code:

package com.example.composeloginapp


import android.os.Bundle

import androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.compose.foundation.background

import androidx.compose.foundation.layout.*

import androidx.compose.foundation.shape.RoundedCornerShape

import androidx.compose.foundation.text.KeyboardOptions

import androidx.compose.material.icons.Icons

import androidx.compose.material.icons.filled.*

import androidx.compose.material3.*

import androidx.compose.runtime.*

import androidx.compose.ui.Modifier

import androidx.compose.ui.graphics.Brush

import androidx.compose.ui.graphics.Color

import androidx.compose.ui.text.input.KeyboardType

import androidx.compose.ui.text.input.PasswordVisualTransformation

import androidx.compose.ui.text.input.VisualTransformation

import androidx.compose.ui.unit.dp

import androidx.compose.ui.Alignment

import androidx.compose.ui.text.font.FontWeight

import androidx.compose.ui.unit.sp

import kotlinx.coroutines.delay

import kotlinx.coroutines.launch


class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContent {

            MaterialTheme(

                colorScheme = darkColorScheme(

                    primary = Color(0xFF6366F1),

                    secondary = Color(0xFF8B5CF6),

                    background = Color(0xFF0F172A)

                )

            ) {

                SimpleAuthApp()

            }

        }

    }

}


// Simulasi database lokal

val dummyUserDB = mutableStateMapOf<String, String>()


@OptIn(ExperimentalMaterial3Api::class)

@Composable

fun SimpleAuthApp() {

    var isLoginScreen by remember { mutableStateOf(true) }

    var username by remember { mutableStateOf("") }

    var email by remember { mutableStateOf("") }

    var password by remember { mutableStateOf("") }

    var confirmPassword by remember { mutableStateOf("") }

    var inputOTP by remember { mutableStateOf("") }

    var generatedOTP by remember { mutableStateOf("") }

    var isOTPSent by remember { mutableStateOf(false) }

    var otpTimer by remember { mutableStateOf(0) }


    var message by remember { mutableStateOf("") }

    var isLoggedIn by remember { mutableStateOf(false) }

    var passwordVisible by remember { mutableStateOf(false) }

    val scope = rememberCoroutineScope()


    val gradient = Brush.verticalGradient(

        listOf(Color(0xFF1E293B), Color(0xFF0F172A))

    )


    Box(

        modifier = Modifier

            .fillMaxSize()

            .background(gradient)

    ) {

        if (isLoggedIn) {

            WelcomeScreen(username) {

                isLoggedIn = false

                username = ""

                password = ""

            }

        } else {

            AuthScreen(

                isLoginScreen, username, email, password, confirmPassword,

                inputOTP, generatedOTP, isOTPSent, otpTimer, passwordVisible, message,

                onUsernameChange = { username = it },

                onEmailChange = { email = it },

                onPasswordChange = { password = it },

                onConfirmPasswordChange = { confirmPassword = it },

                onOTPChange = { inputOTP = it },

                onPasswordVisibilityToggle = { passwordVisible = !passwordVisible },

                onSendOTP = {

                    generatedOTP = (100000..999999).random().toString()

                    isOTPSent = true

                    inputOTP = ""

                    otpTimer = 30

                    scope.launch {

                        while (otpTimer > 0) {

                            delay(1000)

                            otpTimer--

                        }

                    }

                },

                onAuthAction = {

                    if (username.isBlank() || password.isBlank() ||

                        (!isLoginScreen && (email.isBlank() || confirmPassword.isBlank() || inputOTP.isBlank()))

                    ) {

                        message = "Isi semua data terlebih dahulu"

                        return@AuthScreen

                    }


                    if (isLoginScreen) {

                        if (!dummyUserDB.containsKey(username)) {

                            message = "Akun belum terdaftar, silakan daftar terlebih dahulu."

                        } else if (dummyUserDB[username] != password) {

                            message = "Password salah"

                        } else {

                            isLoggedIn = true

                            message = ""

                        }

                    } else {

                        val isUsernameTaken = dummyUserDB.containsKey(username)

                        val isEmailTaken = dummyUserDB.any { it.key == "email:$email" }


                        if (isUsernameTaken || isEmailTaken) {

                            message = "Username atau email sudah terdaftar."

                        } else if (password != confirmPassword) {

                            message = "Password tidak cocok"

                        } else if (inputOTP != generatedOTP) {

                            message = "OTP tidak valid"

                        } else {

                            dummyUserDB[username] = password

                            dummyUserDB["email:$email"] = username

                            message = "Pendaftaran berhasil!"

                            isLoginScreen = true

                            username = ""

                            email = ""

                            password = ""

                            confirmPassword = ""

                            generatedOTP = ""

                            inputOTP = ""

                            isOTPSent = false

                        }

                    }

                },

                onToggleScreen = {

                    isLoginScreen = !isLoginScreen

                    message = ""

                    username = ""

                    email = ""

                    password = ""

                    confirmPassword = ""

                    inputOTP = ""

                    generatedOTP = ""

                    isOTPSent = false

                    otpTimer = 0

                }

            )

        }

    }

}


@Composable

fun WelcomeScreen(username: String, onLogout: () -> Unit) {

    Column(

        modifier = Modifier.fillMaxSize(),

        verticalArrangement = Arrangement.Center,

        horizontalAlignment = Alignment.CenterHorizontally

    ) {

        Text("Selamat datang, $username!", color = Color.White, fontSize = 24.sp)

        Spacer(modifier = Modifier.height(20.dp))

        Button(onClick = onLogout) {

            Text("Logout")

        }

    }

}


@OptIn(ExperimentalMaterial3Api::class)

@Composable

fun AuthScreen(

    isLoginScreen: Boolean,

    username: String,

    email: String,

    password: String,

    confirmPassword: String,

    inputOTP: String,

    generatedOTP: String,

    isOTPSent: Boolean,

    otpTimer: Int,

    passwordVisible: Boolean,

    message: String,

    onUsernameChange: (String) -> Unit,

    onEmailChange: (String) -> Unit,

    onPasswordChange: (String) -> Unit,

    onConfirmPasswordChange: (String) -> Unit,

    onOTPChange: (String) -> Unit,

    onPasswordVisibilityToggle: () -> Unit,

    onSendOTP: () -> Unit,

    onAuthAction: () -> Unit,

    onToggleScreen: () -> Unit

) {

    Column(

        Modifier

            .fillMaxSize()

            .padding(24.dp),

        verticalArrangement = Arrangement.Center,

        horizontalAlignment = Alignment.CenterHorizontally

    ) {

        Text(if (isLoginScreen) "Login" else "Register", fontSize = 28.sp, color = Color.White)

        Spacer(modifier = Modifier.height(16.dp))


        OutlinedTextField(

            value = username,

            onValueChange = onUsernameChange,

            label = { Text("Username") },

            modifier = Modifier.fillMaxWidth(),

            colors = textFieldColors()

        )


        if (!isLoginScreen) {

            Spacer(modifier = Modifier.height(8.dp))

            OutlinedTextField(

                value = email,

                onValueChange = onEmailChange,

                label = { Text("Email") },

                modifier = Modifier.fillMaxWidth(),

                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),

                colors = textFieldColors()

            )

        }


        Spacer(modifier = Modifier.height(8.dp))

        OutlinedTextField(

            value = password,

            onValueChange = onPasswordChange,

            label = { Text("Password") },

            modifier = Modifier.fillMaxWidth(),

            visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),

            trailingIcon = {

                IconButton(onClick = onPasswordVisibilityToggle) {

                    Icon(

                        if (passwordVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff,

                        contentDescription = null

                    )

                }

            },

            colors = textFieldColors()

        )


        if (!isLoginScreen) {

            Spacer(modifier = Modifier.height(8.dp))

            OutlinedTextField(

                value = confirmPassword,

                onValueChange = onConfirmPasswordChange,

                label = { Text("Konfirmasi Password") },

                modifier = Modifier.fillMaxWidth(),

                visualTransformation = PasswordVisualTransformation(),

                colors = textFieldColors()

            )


            Spacer(modifier = Modifier.height(8.dp))


            Button(

                onClick = onSendOTP,

                enabled = otpTimer == 0,

                modifier = Modifier.fillMaxWidth()

            ) {

                Text(if (otpTimer > 0) "Kirim OTP ($otpTimer)" else "Kirim OTP")

            }


            if (generatedOTP.isNotEmpty()) {

                Text("OTP (demo): $generatedOTP", color = Color.Gray, fontSize = 12.sp)

            }


            Spacer(modifier = Modifier.height(8.dp))

            OutlinedTextField(

                value = inputOTP,

                onValueChange = onOTPChange,

                label = { Text("Masukkan OTP") },

                modifier = Modifier.fillMaxWidth(),

                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),

                colors = textFieldColors()

            )

        }


        Spacer(modifier = Modifier.height(16.dp))

        Button(onClick = onAuthAction, modifier = Modifier.fillMaxWidth()) {

            Text(if (isLoginScreen) "Masuk" else "Daftar")

        }


        Spacer(modifier = Modifier.height(8.dp))

        TextButton(onClick = onToggleScreen) {

            Text(

                if (isLoginScreen) "Belum punya akun? Daftar" else "Sudah punya akun? Masuk",

                color = MaterialTheme.colorScheme.primary

            )

        }


        if (message.isNotEmpty()) {

            Spacer(modifier = Modifier.height(12.dp))

            Text(

                text = message,

                color = if (message.contains("berhasil")) Color(0xFF10B981) else Color(0xFFEF4444),

                fontSize = 14.sp

            )

        }

    }

}


@Composable

fun textFieldColors() = OutlinedTextFieldDefaults.colors(

    focusedTextColor = Color.White,

    unfocusedTextColor = Color.White,

    focusedBorderColor = MaterialTheme.colorScheme.primary,

    unfocusedBorderColor = Color.Gray,

    focusedLabelColor = MaterialTheme.colorScheme.primary

)


Komentar

Postingan populer dari blog ini

Tugas 2 - PPB D

Tugas 5 - Simple Calculator