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
Posting Komentar