EAS_202310715200_IndrisAlpasela

This commit is contained in:
202310715200 INDRIS ALPASELA 2026-01-14 21:20:01 +07:00
parent 7cd8b241d0
commit ca6d6e2d33
5 changed files with 451 additions and 169 deletions

View File

@ -5,9 +5,6 @@ import android.util.Base64
import org.json.JSONObject import org.json.JSONObject
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
/**
* Data class untuk menyimpan informasi absensi mahasiswa
*/
data class Absensi( data class Absensi(
val npm: String, val npm: String,
val nama: String, val nama: String,
@ -16,30 +13,21 @@ data class Absensi(
val waktu: String, val waktu: String,
val foto: Bitmap val foto: Bitmap
) { ) {
/**
* Convert objek Absensi ini menjadi JSONObject
* Siap untuk dikirim ke server
*/
fun toJson(): JSONObject { fun toJson(): JSONObject {
val json = JSONObject() val json = JSONObject()
json.put("npm", npm) json.put("npm", npm)
json.put("nama", nama) json.put("nama", nama)
json.put("latitude", latitude) json.put("latitude", latitude)
json.put("longitude", longitude) json.put("longitude", longitude)
json.put("timestamp", System.currentTimeMillis())
json.put("waktu", waktu) json.put("waktu", waktu)
json.put("foto_base64", bitmapToBase64(foto))
// Convert Bitmap to Base64
val byteArrayOutputStream = ByteArrayOutputStream()
foto.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream)
val byteArray = byteArrayOutputStream.toByteArray()
val encodedImage = Base64.encodeToString(byteArray, Base64.DEFAULT)
json.put("foto", encodedImage)
return json return json
} }
companion object {
/**
* Helper function untuk convert Bitmap ke Base64
*/
fun bitmapToBase64(bitmap: Bitmap): String {
val outputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream)
return Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP)
}
}
} }

View File

@ -92,7 +92,7 @@ fun LoginScreen(modifier: Modifier = Modifier) {
// Tombol Login // Tombol Login
Button( Button(
onClick = { onClick = {
if (npm == "202310715123" && password == "123") { if (npm == "202310715200" && password == "123") {
val intent = Intent(context, MainActivity::class.java) val intent = Intent(context, MainActivity::class.java)
context.startActivity(intent) context.startActivity(intent)
} else { } else {

View File

@ -14,21 +14,22 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.google.android.gms.location.LocationServices import com.google.android.gms.location.LocationServices
@ -38,7 +39,11 @@ import java.util.*
import kotlin.concurrent.thread import kotlin.concurrent.thread
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
import org.json.JSONObject
// Warna Akademik Biru Konsisten
val AkademikBlue = Color(0xFF1565C0)
val AkademikLightBlue = Color(0xFFE3F2FD)
val AkademikDarkBlue = Color(0xFF0D47A1)
// ================== UTILS ================== // ================== UTILS ==================
fun kirimKeN8n(context: ComponentActivity, absensi: Absensi) { fun kirimKeN8n(context: ComponentActivity, absensi: Absensi) {
@ -55,14 +60,14 @@ fun kirimKeN8n(context: ComponentActivity, absensi: Absensi) {
context.runOnUiThread { context.runOnUiThread {
Toast.makeText( Toast.makeText(
context, context,
if (responseCode == 200) "Absensi diterima server" else "Absensi ditolak server", if (responseCode == 200) "Absensi berhasil dikirim" else "Absensi gagal dikirim",
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }
conn.disconnect() conn.disconnect()
} catch (_: Exception) { } catch (_: Exception) {
context.runOnUiThread { context.runOnUiThread {
Toast.makeText(context, "Gagal kirim ke server", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Gagal terhubung ke server", Toast.LENGTH_SHORT).show()
} }
} }
} }
@ -77,8 +82,11 @@ class MainActivity : ComponentActivity() {
setContent { setContent {
SistemAkademikTheme { SistemAkademikTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Surface(
AbsensiScreen(modifier = Modifier.padding(innerPadding), activity = this) modifier = Modifier.fillMaxSize(),
color = AkademikLightBlue
) {
AbsensiScreen(activity = this)
} }
} }
} }
@ -86,30 +94,23 @@ class MainActivity : ComponentActivity() {
} }
// ================== COMPOSABLE UI ================== // ================== COMPOSABLE UI ==================
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun AbsensiScreen(modifier: Modifier = Modifier, activity: ComponentActivity) { fun AbsensiScreen(activity: ComponentActivity) {
val context = LocalContext.current val context = LocalContext.current
val session = remember { SessionManager(context) } val session = remember { SessionManager(context) }
var lokasi by remember { mutableStateOf("Koordinat: -") } var lokasi by remember { mutableStateOf("Menunggu lokasi...") }
var latitude by remember { mutableStateOf<Double?>(null) } var latitude by remember { mutableStateOf<Double?>(null) }
var longitude by remember { mutableStateOf<Double?>(null) } var longitude by remember { mutableStateOf<Double?>(null) }
var foto by remember { mutableStateOf<Bitmap?>(null) } var foto by remember { mutableStateOf<Bitmap?>(null) }
var waktuAbsensi by remember { mutableStateOf<String?>(null) } var waktuAbsensi by remember { mutableStateOf<String?>(null) }
var isLoading by remember { mutableStateOf(false) }
var showLogoutDialog by remember { mutableStateOf(false) }
val absensiList = remember { mutableStateListOf<Absensi>() } val absensiList = remember { mutableStateListOf<Absensi>() }
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
// ================== STATE WARNA ==================
var primaryColor by remember { mutableStateOf(Color(0xFF6200EE)) }
var backgroundColor by remember { mutableStateOf(Color(0xFFF2F2F2)) }
val colors = listOf(
Color.Red, Color.Green, Color.Blue, Color.Magenta, Color.Cyan,
Color.Yellow, Color.Gray, Color.DarkGray, Color.Black, Color(0xFFFF9800),
Color(0xFF9C27B0), Color(0xFF4CAF50), Color(0xFF03A9F4), Color(0xFFE91E63)
)
// ===== Permission & Kamera ===== // ===== Permission & Kamera =====
val locationPermissionLauncher = val locationPermissionLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
@ -122,7 +123,7 @@ fun AbsensiScreen(modifier: Modifier = Modifier, activity: ComponentActivity) {
if (location != null) { if (location != null) {
latitude = location.latitude latitude = location.latitude
longitude = location.longitude longitude = location.longitude
lokasi = "Lat: ${location.latitude}\nLon: ${location.longitude}" lokasi = "${String.format("%.6f", location.latitude)}, ${String.format("%.6f", location.longitude)}"
} else { } else {
lokasi = "Lokasi tidak tersedia" lokasi = "Lokasi tidak tersedia"
} }
@ -130,7 +131,7 @@ fun AbsensiScreen(modifier: Modifier = Modifier, activity: ComponentActivity) {
.addOnFailureListener { lokasi = "Gagal mengambil lokasi" } .addOnFailureListener { lokasi = "Gagal mengambil lokasi" }
} }
} else { } else {
Toast.makeText(context, "Izin lokasi ditolak", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Izin lokasi diperlukan", Toast.LENGTH_SHORT).show()
} }
} }
@ -156,7 +157,7 @@ fun AbsensiScreen(modifier: Modifier = Modifier, activity: ComponentActivity) {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraLauncher.launch(intent) cameraLauncher.launch(intent)
} else { } else {
Toast.makeText(context, "Izin kamera ditolak", Toast.LENGTH_SHORT).show() Toast.makeText(context, "Izin kamera diperlukan", Toast.LENGTH_SHORT).show()
} }
} }
@ -164,117 +165,400 @@ fun AbsensiScreen(modifier: Modifier = Modifier, activity: ComponentActivity) {
locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} }
// Logout Dialog
if (showLogoutDialog) {
AlertDialog(
onDismissRequest = { showLogoutDialog = false },
title = { Text("Konfirmasi Keluar") },
text = { Text("Apakah Anda yakin ingin keluar dari sistem?") },
confirmButton = {
TextButton(
onClick = {
session.logout()
context.startActivity(Intent(context, LoginActivity::class.java))
(context as ComponentActivity).finish()
}
) {
Text("Ya", color = Color.Red, fontWeight = FontWeight.Bold)
}
},
dismissButton = {
TextButton(onClick = { showLogoutDialog = false }) {
Text("Batal", color = AkademikBlue)
}
}
)
}
// ================== UI ================== // ================== UI ==================
Scaffold(
topBar = {
TopAppBar(
title = {
Column {
Text(
"Sistem Absensi Mahasiswa",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
Text(
"Universitas Bhayangkara Jakarta Raya",
style = MaterialTheme.typography.bodySmall
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = AkademikBlue,
titleContentColor = Color.White
),
actions = {
TextButton(onClick = { showLogoutDialog = true }) {
Text("Keluar", color = Color.White, fontWeight = FontWeight.Bold)
}
}
)
}
) { paddingValues ->
Column( Column(
modifier = modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(backgroundColor) .padding(paddingValues)
.padding(24.dp) .padding(16.dp)
) {
// CARD PROFIL MAHASISWA
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White
),
elevation = CardDefaults.cardElevation(defaultElevation = 3.dp)
) {
Row(
modifier = Modifier.padding(20.dp),
verticalAlignment = Alignment.CenterVertically
) {
Surface(
modifier = Modifier.size(70.dp),
shape = RoundedCornerShape(12.dp),
color = AkademikLightBlue
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) { ) {
Text( Text(
text = "Absensi Akademik", "IA",
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold,
color = AkademikBlue
)
}
}
Spacer(modifier = Modifier.width(16.dp))
Column {
Text(
text = session.getUserName() ?: "Indris Alpasela",
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
color = primaryColor fontWeight = FontWeight.Bold,
color = AkademikDarkBlue
) )
Text(
text = "NPM: ${session.getUserNpm() ?: "202310715200"}",
style = MaterialTheme.typography.bodyLarge,
color = Color.Gray
)
}
}
}
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
// PALETTE WARNA BULETAN // INFO CARD: LOKASI & WAKTU
Text("Pilih Warna Tema:", style = MaterialTheme.typography.bodyMedium, color = primaryColor) Card(
Spacer(modifier = Modifier.height(8.dp)) modifier = Modifier.fillMaxWidth(),
Row(modifier = Modifier.horizontalScroll(rememberScrollState())) { shape = RoundedCornerShape(12.dp),
colors.forEach { color -> colors = CardDefaults.cardColors(containerColor = Color.White),
Box( elevation = CardDefaults.cardElevation(defaultElevation = 3.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
// Lokasi
Row(verticalAlignment = Alignment.Top) {
Text(
"📍",
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
"Lokasi Saat Ini",
style = MaterialTheme.typography.labelMedium,
color = Color.Gray
)
Text(
lokasi,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
}
}
waktuAbsensi?.let {
Spacer(modifier = Modifier.height(16.dp))
Divider()
Spacer(modifier = Modifier.height(16.dp))
// Waktu Absensi
Row(verticalAlignment = Alignment.Top) {
Text(
"🕐",
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.width(12.dp))
Column {
Text(
"Waktu Absensi Terakhir",
style = MaterialTheme.typography.labelMedium,
color = Color.Gray
)
Text(
it,
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Medium
)
}
}
}
}
}
Spacer(modifier = Modifier.height(16.dp))
// PREVIEW FOTO
AnimatedVisibility(visible = foto != null) {
Column {
Card(
modifier = Modifier modifier = Modifier
.size(40.dp) .fillMaxWidth()
.padding(4.dp) .height(240.dp),
.background(color, shape = CircleShape) shape = RoundedCornerShape(12.dp),
.clickable { elevation = CardDefaults.cardElevation(defaultElevation = 3.dp)
primaryColor = color ) {
backgroundColor = color.copy(alpha = 0.1f) Box(modifier = Modifier.fillMaxSize()) {
foto?.let {
Image(
bitmap = it.asImageBitmap(),
contentDescription = "Preview Foto",
modifier = Modifier.fillMaxSize()
)
} }
Surface(
modifier = Modifier
.align(Alignment.TopEnd)
.padding(8.dp),
shape = RoundedCornerShape(8.dp),
color = Color.White.copy(alpha = 0.9f)
) {
Text(
"Preview",
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.Bold,
color = AkademikBlue
) )
} }
} }
}
Spacer(modifier = Modifier.height(16.dp))
Text(text = lokasi, color = primaryColor)
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
}
}
// TOMBOL AMBIL FOTO
Button( Button(
onClick = { cameraPermissionLauncher.launch(Manifest.permission.CAMERA) }, onClick = { cameraPermissionLauncher.launch(Manifest.permission.CAMERA) },
modifier = Modifier.fillMaxWidth(), modifier = Modifier
colors = ButtonDefaults.buttonColors(containerColor = primaryColor) .fillMaxWidth()
) { Text("Ambil Foto") } .height(60.dp),
colors = ButtonDefaults.buttonColors(containerColor = AkademikBlue),
shape = RoundedCornerShape(12.dp),
elevation = ButtonDefaults.buttonElevation(defaultElevation = 4.dp)
) {
Text(
"📷",
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.width(12.dp))
Text(
"Ambil Foto",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
}
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
// TOMBOL KIRIM ABSENSI
Button( Button(
onClick = { onClick = {
if (latitude != null && longitude != null && foto != null) { if (latitude != null && longitude != null && foto != null) {
val waktu = SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.getDefault()).format(System.currentTimeMillis()) isLoading = true
val waktu = SimpleDateFormat("dd MMMM yyyy, HH:mm:ss", Locale("id", "ID")).format(System.currentTimeMillis())
waktuAbsensi = waktu waktuAbsensi = waktu
val absensi = Absensi( val absensi = Absensi(
npm = session.getUserNpm() ?: "Faris Naufal Priatna", npm = session.getUserNpm() ?: "202310715200",
nama = session.getUserName() ?: "202310715123", nama = session.getUserName() ?: "Indris Alpasela",
latitude = latitude!!, latitude = latitude!!,
longitude = longitude!!, longitude = longitude!!,
waktu = waktu, waktu = waktu,
foto = foto!! foto = foto!!
) )
kirimKeN8n(activity, absensi) kirimKeN8n(activity, absensi)
absensiList.add(absensi) absensiList.add(0, absensi)
isLoading = false
} else { } else {
Toast.makeText(context, "⚠️ Absensi ditolak: Silahkan Foto Dlu Kocak", Toast.LENGTH_SHORT).show() Toast.makeText(
context,
"Mohon ambil foto dan pastikan lokasi aktif",
Toast.LENGTH_LONG
).show()
} }
}, },
modifier = Modifier.fillMaxWidth(), modifier = Modifier
colors = ButtonDefaults.buttonColors(containerColor = primaryColor) .fillMaxWidth()
) { Text("Kirim Absensi") } .height(60.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF2E7D32)),
Spacer(modifier = Modifier.height(16.dp)) shape = RoundedCornerShape(12.dp),
waktuAbsensi?.let { Text("Waktu Absensi: $it", color = primaryColor) } enabled = !isLoading,
elevation = ButtonDefaults.buttonElevation(defaultElevation = 4.dp)
Spacer(modifier = Modifier.height(16.dp))
// ================== LOGOUT BUTTON ==================
Button(
onClick = {
session.logout()
context.startActivity(Intent(context, LoginActivity::class.java))
(context as ComponentActivity).finish()
},
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = Color.Red)
) { ) {
Text("Logout") if (isLoading) {
CircularProgressIndicator(
color = Color.White,
modifier = Modifier.size(28.dp)
)
} else {
Text(
"✉️",
style = MaterialTheme.typography.headlineMedium
)
Spacer(modifier = Modifier.width(12.dp))
Text(
"Kirim Absensi",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
}
} }
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(20.dp))
Text("Riwayat Kehadiran", color = primaryColor)
// RIWAYAT ABSENSI
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
"Riwayat Kehadiran",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
color = AkademikDarkBlue
)
if (absensiList.isNotEmpty()) {
Surface(
shape = RoundedCornerShape(20.dp),
color = AkademikLightBlue
) {
Text(
"${absensiList.size}",
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
style = MaterialTheme.typography.labelLarge,
fontWeight = FontWeight.Bold,
color = AkademikBlue
)
}
}
}
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
if (absensiList.isEmpty()) Text("Belum ada absensi", color = primaryColor) if (absensiList.isEmpty()) {
else LazyColumn { Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(containerColor = Color.White),
shape = RoundedCornerShape(12.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(40.dp),
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
"📋",
style = MaterialTheme.typography.displayMedium
)
Spacer(modifier = Modifier.height(12.dp))
Text(
"Belum ada riwayat kehadiran",
color = Color.Gray,
style = MaterialTheme.typography.bodyLarge
)
}
}
}
} else {
LazyColumn {
items(absensiList) { item -> items(absensiList) { item ->
Card( Card(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 4.dp), .padding(vertical = 6.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) elevation = CardDefaults.cardElevation(defaultElevation = 3.dp),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(containerColor = Color.White)
) { ) {
Column(modifier = Modifier.padding(12.dp)) { Row(
Text("Nama: ${item.nama}", color = primaryColor) modifier = Modifier.padding(16.dp),
Text("NPM: ${item.npm}", color = primaryColor) verticalAlignment = Alignment.CenterVertically
Text("Waktu: ${item.waktu}", color = primaryColor) ) {
Text("Lat: ${item.latitude}, Lon: ${item.longitude}", color = primaryColor) // Foto Kecil
Spacer(modifier = Modifier.height(8.dp))
Image( Image(
bitmap = item.foto.asImageBitmap(), bitmap = item.foto.asImageBitmap(),
contentDescription = "Foto Absensi", contentDescription = "Foto Absensi",
modifier = Modifier modifier = Modifier
.fillMaxWidth() .size(80.dp)
.height(150.dp) .clip(RoundedCornerShape(8.dp))
)
Spacer(modifier = Modifier.width(16.dp))
// Info
Column(modifier = Modifier.weight(1f)) {
Text(
item.nama,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
color = AkademikDarkBlue
)
Text(
item.npm,
style = MaterialTheme.typography.bodyMedium,
color = Color.Gray
)
Spacer(modifier = Modifier.height(6.dp))
Text(
item.waktu,
style = MaterialTheme.typography.bodySmall,
color = Color.Gray
)
}
// Status
Text(
"",
style = MaterialTheme.typography.headlineMedium
) )
} }
} }
@ -282,3 +566,5 @@ fun AbsensiScreen(modifier: Modifier = Modifier, activity: ComponentActivity) {
} }
} }
} }
}
}

View File

@ -5,29 +5,37 @@ import android.content.SharedPreferences
class SessionManager(context: Context) { class SessionManager(context: Context) {
private val prefs: SharedPreferences = private val prefs: SharedPreferences =
context.getSharedPreferences("user_session", Context.MODE_PRIVATE) context.getSharedPreferences("AbsensiSession", Context.MODE_PRIVATE)
companion object { companion object {
private const val KEY_IS_LOGGED_IN = "is_logged_in" private const val KEY_IS_LOGGED_IN = "isLoggedIn"
private const val KEY_NPM = "npm" private const val KEY_USER_NAME = "userName"
private const val KEY_NAME = "name" private const val KEY_USER_NPM = "userNpm"
} }
fun saveLogin(npm: String, name: String) { fun saveLoginSession(nama: String, npm: String) {
prefs.edit().apply { val editor = prefs.edit()
putBoolean(KEY_IS_LOGGED_IN, true) editor.putBoolean(KEY_IS_LOGGED_IN, true)
putString(KEY_NPM, npm) editor.putString(KEY_USER_NAME, nama)
putString(KEY_NAME, name) editor.putString(KEY_USER_NPM, npm)
apply() editor.apply()
}
} }
fun isLoggedIn(): Boolean = prefs.getBoolean(KEY_IS_LOGGED_IN, false) fun isLoggedIn(): Boolean {
return prefs.getBoolean(KEY_IS_LOGGED_IN, false)
}
fun getUserName(): String? {
return prefs.getString(KEY_USER_NAME, null)
}
fun getUserNpm(): String? {
return prefs.getString(KEY_USER_NPM, null)
}
fun logout() { fun logout() {
prefs.edit().clear().apply() val editor = prefs.edit()
editor.clear()
editor.apply()
} }
fun getUserNpm(): String? = prefs.getString(KEY_NPM, null)
fun getUserName(): String? = prefs.getString(KEY_NAME, null)
} }