Tugas Pertemuan 13 Pemrograman Perangkat Bergerak B

Nama    : Fadaukas Daffa Tajuddin

NRP      : 5025231149

Kelas    : PPB (B)


Membuat Registrasi Siswa

Aplikasi Registrasi Siswa adalah solusi manajemen data siswa sederhana yang memungkinkan pengguna untuk melakukan operasi CRUD (Create, Read, Update, Delete). Aplikasi ini dibangun menggunakan teknologi modern Android yaitu Jetpack Compose untuk antarmuka pengguna dan Room Database untuk penyimpanan data lokal secara persisten.

Komponen Utama

Siswa.kt
package com.example.registrasisiswa.data

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "siswa")
data class Siswa(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val nama: String,
val email: String
)
SiswaDao.kt
package com.example.registrasisiswa.data

import androidx.room.*
import kotlinx.coroutines.flow.Flow

@Dao
interface SiswaDao {
@Query("SELECT * FROM siswa ORDER BY nama ASC")
fun getAllSiswa(): Flow<List<Siswa>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertSiswa(siswa: Siswa)

@Update
suspend fun updateSiswa(siswa: Siswa)

@Delete
suspend fun deleteSiswa(siswa: Siswa)
}
Database
package com.example.registrasisiswa.data

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

@Database(entities = [Siswa::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun siswaDao(): SiswaDao

companion object {
@Volatile
private var Instance: AppDatabase? = null

fun getDatabase(context: Context): AppDatabase {
return Instance ?: synchronized(this) {
Room.databaseBuilder(context, AppDatabase::class.java, "siswa_database")
.build()
.also { Instance = it }
}
}
}
}
StudentViewModel.kt
package com.example.registrasisiswa.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.registrasisiswa.data.Siswa
import com.example.registrasisiswa.data.SiswaDao
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

class StudentViewModel(private val dao: SiswaDao) : ViewModel() {

val allSiswa: StateFlow<List<Siswa>> = dao.getAllSiswa()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = emptyList()
)

fun insertSiswa(nama: String, email: String) {
viewModelScope.launch {
dao.insertSiswa(Siswa(nama = nama, email = email))
}
}

fun updateSiswa(siswa: Siswa) {
viewModelScope.launch {
dao.updateSiswa(siswa)
}
}

fun deleteSiswa(siswa: Siswa) {
viewModelScope.launch {
dao.deleteSiswa(siswa)
}
}
}
FormInput.kt
package com.example.registrasisiswa.ui

import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun FormInput(
onAddClick: (String, String) -> Unit,
modifier: Modifier = Modifier
) {
var nama by remember { mutableStateOf("") }
var email by remember { mutableStateOf("") }

Column(
modifier = modifier
.fillMaxWidth()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
OutlinedTextField(
value = nama,
onValueChange = { nama = it },
label = { Text("Nama") },
modifier = Modifier.fillMaxWidth()
)
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Email") },
modifier = Modifier.fillMaxWidth()
)
Button(
onClick = {
if (nama.isNotBlank() && email.isNotBlank()) {
onAddClick(nama, email)
nama = ""
email = ""
}
},
modifier = Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.medium
) {
Icon(Icons.Default.Add, contentDescription = null)
Spacer(Modifier.width(8.dp))
Text("Tambah Siswa")
}
}
}
StudentItem.kt
package com.example.registrasisiswa.ui

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.registrasisiswa.data.Siswa

@Composable
fun StudentItem(
siswa: Siswa,
onEditClick: () -> Unit,
onDeleteClick: () -> Unit,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Row(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
// Initial Circle
Box(
modifier = Modifier
.size(40.dp)
.background(
color = Color(0xFFE3F2FD),
shape = CircleShape
),
contentAlignment = Alignment.Center
) {
val initial = if (siswa.nama.isNotEmpty()) siswa.nama.take(2).uppercase() else "?"
Text(
text = initial,
color = Color(0xFF1976D2),
fontWeight = FontWeight.Bold,
fontSize = 14.sp
)
}

Spacer(Modifier.width(16.dp))

Column(modifier = Modifier.weight(1f)) {
Text(
text = siswa.nama,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
Text(
text = siswa.email,
style = MaterialTheme.typography.bodySmall,
color = Color.Gray
)
}

IconButton(onClick = onEditClick) {
Icon(
Icons.Default.Edit,
contentDescription = "Edit",
tint = Color(0xFF3F51B5)
)
}
IconButton(onClick = onDeleteClick) {
Icon(
Icons.Default.Delete,
contentDescription = "Delete",
tint = Color(0xFFE57373)
)
}
}
}
}
MainActivity.kt
package com.example.registrasisiswa

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.registrasisiswa.data.AppDatabase
import com.example.registrasisiswa.data.SiswaDao
import com.example.registrasisiswa.ui.MainScreen
import com.example.registrasisiswa.ui.theme.RegistrasiSiswaTheme
import com.example.registrasisiswa.viewmodel.StudentViewModel

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// 1. Inisialisasi database dan DAO
val database = AppDatabase.getDatabase(applicationContext)
val dao = database.siswaDao()

enableEdgeToEdge()
setContent {
RegistrasiSiswaTheme {
// 2. Inisialisasi ViewModel dengan Factory agar bisa menerima parameter DAO
val viewModel: StudentViewModel = viewModel(
factory = StudentViewModelFactory(dao)
)

// 3. Tampilkan Layar Utama
MainScreen(viewModel = viewModel)
}
}
}
}

// Factory untuk membuat StudentViewModel
class StudentViewModelFactory(private val dao: SiswaDao) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(StudentViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return StudentViewModel(dao) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}

Aplikasi




Komentar

Postingan populer dari blog ini

Tugas Pertemuan 12 Pemrograman Perangkat Bergerak B

Tugas Pertemuan 2 Pemrograman Perangkat Bergerak B

Tugas Pertemuan 3 Pemrograman Perangkat Bergerak B