diff --git a/README.md b/README.md index bb634d7..e555863 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,7 @@ Repository ini digunakan untuk praktikum perkuliahan pemrograman mobile. # Kelompok 8 1. Lalu Muhammad Anggana Subhan (202310715277) 2. Muhammad Rafly Al-Fathir (202310715043) -3. Rafi Fattan Fitriardi (202310715002) \ No newline at end of file +3. Rafi Fattan Fitriardi (202310715002) + +Latihan Praktikum 1: +Mengganti logo tombol menjadi lingkar merah dengan menambahkan gambar red_button.jpg \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2b2ac69..6e146bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,6 +22,11 @@ + + + diff --git a/app/src/main/java/id/ac/ubharajaya/panicbutton/JalurEvakuasiActivity.kt b/app/src/main/java/id/ac/ubharajaya/panicbutton/JalurEvakuasiActivity.kt index e79aeab..0a41d2d 100644 --- a/app/src/main/java/id/ac/ubharajaya/panicbutton/JalurEvakuasiActivity.kt +++ b/app/src/main/java/id/ac/ubharajaya/panicbutton/JalurEvakuasiActivity.kt @@ -1,2 +1,47 @@ package id.ac.ubharajaya.panicbutton +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp + +class JalurEvakuasiActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + JalurEvakuasiScreen(onClose = { finish() }) + } + } +} + +@Composable +fun JalurEvakuasiScreen(onClose: () -> Unit) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + + Image( + painter = painterResource(id = R.drawable.evakuasi), + contentDescription = "Jalur Evakuasi", + modifier = Modifier.fillMaxWidth() + ) + + Spacer(modifier = Modifier.height(20.dp)) + + Button(onClick = onClose) { + Text("Close") + } + } +} diff --git a/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt b/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt index 4c0a4d7..cb95295 100644 --- a/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt +++ b/app/src/main/java/id/ac/ubharajaya/panicbutton/MainActivity.kt @@ -1,18 +1,25 @@ package id.ac.ubharajaya.panicbutton +import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.Image +import androidx.compose.foundation.border import androidx.compose.foundation.clickable -import androidx.compose.material3.Button -import androidx.compose.material3.Text +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp -import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.sp import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.Request @@ -22,67 +29,189 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - MyApp() + MyApp( + onClose = { finish() }, + onOpenEvacuation = { + startActivity(Intent(this, JalurEvakuasiActivity::class.java)) + } + ) } } } +// Emoji untuk tiap kondisi +fun getEmoji(condition: String): String { + return when (condition) { + "Kebakaran" -> "🔥" + "Banjir" -> "⛈️" + "Tsunami" -> "🌊" + "Gunung Meletus" -> "🌋" + "Gempa Bumi" -> "🌏" + "Huru Hara/Demonstrasi" -> "👿" + "Binatang Buas" -> "🐍" + "Radiasi Nuklir" -> "☢️" + "Biohazard" -> "☣️" + else -> "" + } +} @Composable -fun MyApp() { +fun MyApp(onClose: () -> Unit, onOpenEvacuation: () -> Unit) { + val focusManager = LocalFocusManager.current var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") } + var selectedConditions by remember { mutableStateOf(mutableSetOf()) } + var additionalNotes by remember { mutableStateOf(TextFieldValue("")) } Column( modifier = Modifier .fillMaxSize() .padding(16.dp), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.Start ) { - Text(text = message, Modifier.padding(bottom = 16.dp)) + // Judul + Text( + text = "Terjadi Kondisi Darurat:", + fontSize = 26.sp, + fontWeight = FontWeight.Bold, + color = Color.Red, + modifier = Modifier.padding(bottom = 16.dp) + ) - // Ganti Button dengan ImageButton versi Compose - androidx.compose.foundation.Image( - painter = painterResource(id = R.drawable.red_button), - contentDescription = "Tombol merah", + // Daftar kondisi + listOf( + "Kebakaran", + "Banjir", + "Tsunami", + "Gunung Meletus", + "Gempa Bumi", + "Huru Hara/Demonstrasi", + "Binatang Buas", + "Radiasi Nuklir", + "Biohazard", + "Lainnya" + ).forEach { condition -> + val emoji = getEmoji(condition) + + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + focusManager.clearFocus() + selectedConditions = selectedConditions.toMutableSet().apply { + if (contains(condition)) remove(condition) else add(condition) + } + } + .padding(vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = selectedConditions.contains(condition), + onCheckedChange = { isChecked -> + focusManager.clearFocus() + selectedConditions = selectedConditions.toMutableSet().apply { + if (isChecked) add(condition) else remove(condition) + } + } + ) + Text( + text = "$emoji $condition", + modifier = Modifier.padding(start = 8.dp) + ) + } + } + + // Catatan tambahan + Spacer(modifier = Modifier.height(16.dp)) + Text(text = "Catatan tambahan:", fontWeight = FontWeight.Bold) + + BasicTextField( + value = additionalNotes, + onValueChange = { additionalNotes = it }, modifier = Modifier - .size(145.dp, 365.dp) - .clickable { - sendNotification { response -> + .fillMaxWidth() + .height(100.dp) + .padding(8.dp) + .border(1.dp, Color.Gray), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done) + ) + + // ================================================ + // Tombol Kirim + Lihat Jalur Evakuasi (Berdampingan) + // ================================================ + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + + // Tombol Kirim Laporan + Button( + onClick = { + val notes = additionalNotes.text + val conditions = selectedConditions.joinToString(", ") { + "${getEmoji(it)} $it" + } + val report = "Kondisi: $conditions\nCatatan: $notes" + + sendNotification(report) { response -> message = response } - } + }, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors(containerColor = Color.Red) + ) { + Text(text = "Kirim Laporan", color = Color.White) + } + + Spacer(modifier = Modifier.width(12.dp)) + + // Tombol Jalur Evakuasi + Button( + onClick = onOpenEvacuation, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF0080FF)) + ) { + Text(text = "Lihat Jalur Evakuasi", color = Color.White) + } + } + + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "“JANGAN PANIK! SEGERA EVAKUASI\nDIRI ANDA KE TITIK KUMPUL”", + color = Color.Red, + fontSize = 15.sp ) + + Spacer(modifier = Modifier.height(20.dp)) + + // Tombol Tutup (opsional) + Button(onClick = onClose) { + Text("Tutup") + } + + Spacer(modifier = Modifier.height(16.dp)) + Text(text = message) } } - - -// Fungsi untuk mengirimkan HTTP request -fun sendNotification(onResult: (String) -> Unit) { +// =============================================================== +// Fungsi Kirim Notifikasi ke Server ntfy.ubharajaya.ac.id +// =============================================================== +fun sendNotification(report: String, onResult: (String) -> Unit) { val client = OkHttpClient() - val url = "https://ntfy.ubharajaya.ac.id/panic-button" // Ganti dengan topik Anda - - - - - val requestBody = RequestBody.create( - "text/plain".toMediaType(), // Mengirim plain text - "Notifikasi dari Kelompok 8 (Lalu Angga, M Rafly, Rafi Fattan)" // Pesan yang akan tampil - ) + val url = "https://ntfy.ubharajaya.ac.id/panic-button" + val requestBody = RequestBody.create("text/plain".toMediaType(), report) val request = Request.Builder() .url(url) .addHeader("Title", "Alert") .addHeader("Priority", "urgent") - .addHeader("Tags", "alert warning,rotating_light") .post(requestBody) .build() - - - // Eksekusi request di thread terpisah Thread { try { val response = client.newCall(request).execute() @@ -95,4 +224,4 @@ fun sendNotification(onResult: (String) -> Unit) { onResult("Error: ${e.message}") } }.start() -} \ No newline at end of file +} diff --git a/app/src/main/res/drawable/evakuasi.png b/app/src/main/res/drawable/evakuasi.png new file mode 100644 index 0000000..9a7688a Binary files /dev/null and b/app/src/main/res/drawable/evakuasi.png differ