Compare commits

..

6 Commits

9 changed files with 38 additions and 286 deletions

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

View File

@ -9,7 +9,6 @@ Repository ini digunakan untuk praktikum perkuliahan pemrograman mobile.
- Arif Dwiyanto: arif.dwiyanto@ubharajaya.ac.id
## Mahasiswa
<<<<<<< HEAD
- 1. Dendi Yogia Pratama (202310715051)
- 2. Nuryuda Maulana (202310715038)
- 3. Haga Dalpinto Ginting (202310715176)
@ -27,16 +26,11 @@ Repository ini digunakan untuk praktikum perkuliahan pemrograman mobile.
- 15. Indris Alpasela (202310715200)
- 16. Raihan Ariq Muzakki (202310715297)
- 17. Dirson Ali Wardana (202310715246)
<<<<<<< HEAD
- 18. Dimas Hendri Pamungkas (202310715274)
- 19. Fadhlul Wafi (202310715188)
- 20. Muhammad Yusron Amrullah (202310715060)
- 21. Muhammad Fadillah (202310715213)
- 21. Hadi Guna Prakoso (202310715312)
=======
=======
- Fadlan Rivaldi (202310715280)
- B
- C
>>>>>>> d4f073d (First Commit)
>>>>>>> 59a5f2b68a9a33028bb744220857c043749c6949
- 22. Hadi Guna Prakoso (202310715312)
- 23. Muhammad Rafi (202310715191)
- 24. Muhammad Rafly Al-Fathir (202310715043)
- 25. Jeremia Sebastian Marpaung (202310715096)

View File

@ -57,9 +57,6 @@ dependencies {
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest)
implementation("com.squareup.okhttp3:okhttp:4.11.0")
implementation("androidx.compose.material3:material3:1.1.1")
//praktikum 1
implementation("com.squareup.okhttp3:okhttp:4.11.0")
implementation("androidx.compose.material3:material3:1.1.1")

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
@ -11,9 +10,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PanicButton"
tools:targetApi="31">
android:theme="@style/Theme.PanicButton">
<activity
android:name=".MainActivity"
android:exported="true"
@ -21,17 +18,10 @@
android:theme="@style/Theme.PanicButton">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".JalurEvakuasiActivity"
android:exported="false"
android:label="Jalur Evakuasi"
android:theme="@style/Theme.PanicButton" />
</application>
</manifest>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@ -1,54 +0,0 @@
package id.ac.ubharajaya.panicbutton
import android.app.Activity
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.layout.ContentScale // <-- TAMBAHKAN IMPORT INI
import androidx.compose.ui.platform.LocalContext
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()
}
}
}
@Composable
fun JalurEvakuasiScreen() {
val context = LocalContext.current
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(
painter = painterResource(id = R.drawable.jalur_evakuasi),
contentDescription = "Denah Jalur Evakuasi",
modifier = Modifier
.fillMaxWidth()
.weight(1f),
contentScale = ContentScale.Fit
)
Button(
onClick = {
(context as? Activity)?.finish()
},
modifier = Modifier.padding(vertical = 16.dp)
) {
Text(text = "TUTUP")
}
}
}

View File

@ -1,30 +1,18 @@
package id.ac.ubharajaya.panicbutton
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.tooling.preview.Preview
import id.ac.ubharajaya.panicbutton.ui.theme.PanicButtonTheme
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
@ -33,184 +21,32 @@ import okhttp3.RequestBody
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MyApp()
PanicButtonTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun MyApp() {
val context = LocalContext.current
var message by remember { mutableStateOf("Kirim laporan untuk mendapatkan notifikasi") }
var selectedConditions by remember { mutableStateOf(mutableSetOf<String>()) }
var additionalNotes by remember { mutableStateOf(TextFieldValue("")) }
// Map untuk mencocokkan teks UI dengan tag untuk API
val conditionToTagMap = mapOf(
"🔥 Kebakaran" to "fire",
"⛈️ Banjir" to "cloud_with_rain",
"🌊 Tsunami" to "ocean",
"🌋 Gunung Meletus" to "volcano",
"🌏 Gempa Bumi" to "earth_asia",
"👿 Huru Hara" to "imp",
"🐍 Binatang Buas" to "snake",
"☢️ Radiasi Nuklir" to "radioactive",
"☣️ Biohazard" to "biohazard"
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
// Daftar kondisi untuk ditampilkan di UI
val conditions = conditionToTagMap.keys.toList()
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
.verticalScroll(scrollState), // Membuat Column bisa di-scroll
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start
) {
// --- Bagian Judul ---
Text(
text = "Terjadi Kondisi Darurat",
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = Color.Red,
modifier = Modifier.padding(bottom = 16.dp)
)
// --- Bagian Daftar Checkbox ---
// Perulangan ini HANYA untuk membuat baris Checkbox
conditions.forEach { condition ->
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable {
// Logika untuk menambah/menghapus dari set
val newSet = selectedConditions.toMutableSet()
if (newSet.contains(condition)) {
newSet.remove(condition)
} else {
newSet.add(condition)
}
selectedConditions = newSet
}
.padding(vertical = 4.dp)
) {
Checkbox(
checked = selectedConditions.contains(condition),
onCheckedChange = { isChecked ->
val newSet = selectedConditions.toMutableSet()
if (isChecked) {
newSet.add(condition)
} else {
newSet.remove(condition)
}
selectedConditions = newSet
}
)
Text(text = condition, modifier = Modifier.padding(start = 8.dp))
}
}
// --- Bagian Catatan Tambahan ---
Spacer(modifier = Modifier.height(16.dp))
Text(text = "Catatan tambahan:")
BasicTextField(
value = additionalNotes,
onValueChange = { additionalNotes = it },
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.padding(vertical = 8.dp)
.border(1.dp, Color.Gray),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done)
)
// --- Bagian Tombol Kirim Laporan ---
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
val notes = additionalNotes.text
// Ambil tag yang sesuai dari map, bukan teks dari UI
val tags = selectedConditions.mapNotNull { conditionToTagMap[it] }.joinToString(",")
val report = "Kondisi: ${selectedConditions.joinToString(", ")}\nCatatan: $notes"
// Panggilan ini sekarang berada di scope yang benar
sendNotification(report, tags) { response ->
message = response
}
},
colors = ButtonDefaults.buttonColors(containerColor = Color.Red),
modifier = Modifier.fillMaxWidth()
) {
Text(text = "Kirim Laporan", color = Color.White)
}
// --- Bagian Keterangan Evakuasi ---
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "“JANGAN PANIK! SEGERA EVAKUASI\nDIRI ANDA KE TITIK KUMPUL”",
color = Color.Red,
fontSize = 15.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.align(Alignment.CenterHorizontally)
)
// --- Bagian Hasil Request ---
Spacer(modifier = Modifier.height(16.dp))
Text(text = message, modifier = Modifier.padding(top = 16.dp))
// Spacer untuk mendorong tombol bawah ke dasar layar
Spacer(modifier = Modifier.weight(1f))
// --- Bagian Tombol Bawah ---
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(onClick = {
context.startActivity(Intent(context, JalurEvakuasiActivity::class.java))
}) {
Text(text = "Lihat Jalur Evakuasi")
}
Button(
onClick = { (context as? Activity)?.finish() },
colors = ButtonDefaults.buttonColors(containerColor = Color.Gray)
) {
Text(text = "Tutup", color = Color.White)
}
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
PanicButtonTheme {
Greeting("Android")
}
}
// Fungsi sendNotification (tidak perlu diubah)
fun sendNotification(report: String, tags: String, onResult: (String) -> Unit) {
// ... implementasi sudah benar
val client = OkHttpClient()
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", tags)
.post(requestBody)
.build()
Thread {
try {
val response = client.newCall(request).execute()
if (response.isSuccessful) {
onResult("Notifikasi berhasil dikirim!")
} else {
onResult("Gagal mengirim notifikasi: ${response.code}")
}
} catch (e: Exception) {
onResult("Error: ${e.message}")
}
}.start()
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View File

@ -1,4 +1,3 @@
<resources>
<string name="app_name">Panic Button</string>
<string name="send_alert">Kirim Alert</string>
</resources>
</resources>