Mengubah Tag sesuai Kiriman User dan Menambahkan Activity baru untuk Jalur Evakuasi

This commit is contained in:
202310715297 RAIHAN ARIQ MUZAKKI 2025-11-20 15:38:38 +07:00
parent e855ff870c
commit 48d1205ba8
5 changed files with 215 additions and 25 deletions

View File

@ -50,6 +50,7 @@ dependencies {
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.foundation)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)

View File

@ -17,16 +17,19 @@
android:theme="@style/Theme.PanicButton">
<activity
android:name="com.example.panicbutton.MainActivity"
android:name="id.ac.ubharajaya.panicbutton.MainActivity"
android:exported="true"
android:label="@string/app_name"
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" />
</application>
</manifest>

View File

@ -0,0 +1,62 @@
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.material3.ButtonDefaults
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.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
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
) {
Text(
text = "Jalur Evakuasi",
fontSize = 20.sp,
)
Spacer(modifier = Modifier.height(16.dp))
// Menampilkan gambar denah
Image(
painter = painterResource(id = R.drawable.jalur_evakuasi),
contentDescription = "Denah Jalur Evakuasi",
modifier = Modifier
.fillMaxWidth()
.height(450.dp)
)
Spacer(modifier = Modifier.height(20.dp))
// Tombol Close
Button(
onClick = { onClose() },
colors = ButtonDefaults.buttonColors(containerColor = Color.Red)
) {
Text(text = "Close", color = Color.White)
}
}
}

View File

@ -1,18 +1,33 @@
package com.example.panicbutton
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.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
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.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import java.util.concurrent.locks.Condition
class MainActivity : ComponentActivity() {
@ -27,55 +42,162 @@ class MainActivity : ComponentActivity() {
@Composable
fun MyApp() {
// State untuk menampilkan hasil request
val focusManager = LocalFocusManager.current
var message by remember { mutableStateOf("Klik tombol untuk mengirim notifikasi") }
var selectedConditions by remember { mutableStateOf(mutableSetOf<String>()) }
var additionalNotes by remember { mutableStateOf(TextFieldValue("")) }
// Agar bisa Scroll
val scrollState = rememberScrollState()
val context = LocalContext.current
// UI
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start
) {
Text(text = message, Modifier.padding(bottom = 16.dp))
Button(onClick = {
// Kirim HTTP request saat tombol ditekan
sendNotification { response ->
message = response
Text(
text = "Terjadi Kondisi Darurat",
fontSize = 20.sp,
color = Color.Red,
modifier = Modifier.padding(bottom = 16.dp)
)
listOf(
"Kebakaran", "Banjir", "Tsunami", "Gunung Meletus",
"Gempa Bumi", "Huru hara", "Binatang Buas",
"Radiasi Nuklir", "Biohazard"
).forEach { 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 = condition,
modifier = Modifier.padding(start = 8.dp)
)
}
}) {
Text(text = "Kirim Alert")
}
Spacer(modifier = Modifier.height(16.dp))
Text(text = "Catatan tambahan:")
BasicTextField(
value = additionalNotes,
onValueChange = { additionalNotes = it },
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.padding(8.dp)
.border(1.dp, Color.Gray),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done)
)
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = {
val notes = additionalNotes.text
val conditions = selectedConditions.joinToString(", ")
val report = "Kondisi: $conditions\nCatatan: $notes"
sendNotification(conditions, report) { response ->
message = response
}
},
colors = ButtonDefaults.buttonColors(containerColor = Color.Red)
) {
Text(text = "Kirim Laporan", 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(16.dp))
Text(text = message, Modifier.padding(top = 16.dp))
Button(
onClick = {
val intent = Intent(context, JalurEvakuasiActivity::class.java)
context.startActivity(intent)
},
colors = ButtonDefaults.buttonColors(containerColor = Color.Green)
) {
Text(text = "Lihat Jalur Evakuasi", color = Color.White)
}
}
}
// Fungsi untuk mengirimkan HTTP request
fun sendNotification(onResult: (String) -> Unit) {
fun sendNotification(condition: String, report: String, onResult: (String) -> Unit) {
val client = OkHttpClient()
val url = "https://ntfy.ubharajaya.ac.id/panic-button" // Ganti <your-topic> dengan topik Anda
val url = "https://ntfy.ubharajaya.ac.id/panic-button"
val requestBody = RequestBody.create(
"text/plain".toMediaType(), // Mengirim plain text
"Notifikasi dari Kelompok 1 (Raihan, Dendi, Fazri)!" // Pesan yang akan tampil
// Mapping kondisi → emoji/tag
val tagMapping = mapOf(
"Kebakaran" to "fire",
"Banjir" to "ocean",
"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"
)
// Bersihkan kondisi: trim + filter
val selectedList = condition
.split(",")
.map { it.trim() }
.filter { it.isNotEmpty() }
// Format ulang kondisi
val cleanConditionText = selectedList.joinToString(", ")
// Ambil emoji untuk masing-masing kondisi
val emojiTags = selectedList.mapNotNull { tagMapping[it] }
// Tambahkan default tag: alert + warning
val finalTags = listOf("Alert", "Warning") + emojiTags
val finalReport = "Kondisi: $cleanConditionText\nCatatan: ${report.substringAfter("Catatan:")}"
val requestBody = RequestBody.create(
"text/plain".toMediaType(),
finalReport
)
val request = Request.Builder()
.url(url)
.addHeader("Title", "Radioactive")
.addHeader("Title", "Alert")
.addHeader("Priority", "urgent")
.addHeader("Tags", "alert warning,rotating_light")
.addHeader("Tags", finalTags.joinToString(","))
.post(requestBody)
.build()
// Eksekusi request di thread terpisah
Thread {
try {
val response = client.newCall(request).execute()

View File

@ -8,6 +8,7 @@ espressoCore = "3.7.0"
lifecycleRuntimeKtx = "2.9.4"
activityCompose = "1.11.0"
composeBom = "2024.09.00"
foundation = "1.9.4"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -24,6 +25,7 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundation" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }