feat(ui): checklist report types with emoji icons; improved card styling and 3D panic button

This commit is contained in:
Rakha adi 2025-11-19 21:30:38 +07:00
parent 97d37a43ad
commit f0d6074b55
3 changed files with 90 additions and 33 deletions

View File

@ -13,6 +13,9 @@
<option value="f607f271-4885-4c4e-91da-e2caf2abd67a" />
<option value="39a0d9c4-a68f-4050-bb14-eda17dc695db" />
<option value="94d90579-6a6d-44a9-8b93-de694c0c38ef" />
<option value="fe272d92-3acf-42e8-bd88-66dc00800c3f" />
<option value="ea6afe5a-c296-461b-a4a7-49209b3d7937" />
<option value="2b41e5bf-4d90-46d8-8fc8-7b41c3f788e1" />
</set>
</value>
</entry>

18
.idea/copilotDiffState.xml generated Normal file

File diff suppressed because one or more lines are too long

View File

@ -46,54 +46,89 @@ fun MyApp() {
// dialogMessage akan menampung hasil callback dari sendNotification; null = tidak tampil
var dialogMessage by remember { mutableStateOf<String?>(null) }
// Report options (checkbox-style)
val reportOptions = listOf("Kebakaran", "Banjir", "Gempa Bumi", "Huru Hara/Demostrasi", "Lainnya")
val checkedMap = remember { mutableStateMapOf<String, Boolean>().apply { reportOptions.forEach { put(it, false) } } }
// theme color for panic
val panicColor = Color(0xFFB71C1C)
// Report options (checkbox-style) with icons (emoji from ntfy emoji list)
val reportOptions = listOf(
"Kebakaran" to "🔥",
"Banjir" to "🌊",
"Gempa Bumi" to "🌍",
"Huru Hara/Demostrasi" to "📣",
"Lainnya" to "📝"
)
val checkedMap = remember { mutableStateMapOf<String, Boolean>().apply { reportOptions.forEach { put(it.first, false) } } }
var otherNote by remember { mutableStateOf("") }
// UI
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
.padding(18.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// Checklist area similar to the wireframe
// Checklist area styled as card
Surface(
tonalElevation = 2.dp,
shape = RoundedCornerShape(8.dp),
color = Color(0xFFFFEBEE), // soft red/pink background to match panic theme
tonalElevation = 4.dp,
shape = RoundedCornerShape(10.dp),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
.fillMaxWidth(0.92f)
.padding(horizontal = 12.dp)
) {
Column(modifier = Modifier.padding(12.dp)) {
Text(text = "Terjadi Kondisi Darurat", fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.height(8.dp))
Column(modifier = Modifier.padding(14.dp)) {
Text(
text = "Terjadi Kondisi Darurat",
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
color = panicColor
)
// Each option as a row with checkbox
reportOptions.forEach { option ->
Spacer(modifier = Modifier.height(10.dp))
// Each option as a row with icon, label and checkbox aligned nicely
reportOptions.forEach { (label, icon) ->
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
.padding(vertical = 6.dp)
.toggleable(
value = checkedMap[option] ?: false,
onValueChange = { checked -> checkedMap[option] = checked }
value = checkedMap[label] ?: false,
onValueChange = { checked -> checkedMap[label] = checked }
)
) {
// icon circle
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.size(34.dp)
.background(color = Color.White.copy(alpha = 0.9f), shape = CircleShape)
.shadow(1.dp, shape = CircleShape)
) {
Text(text = icon, fontSize = 18.sp)
}
Spacer(modifier = Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) {
Text(text = label, fontSize = 16.sp)
}
Checkbox(
checked = checkedMap[option] ?: false,
onCheckedChange = { checked -> checkedMap[option] = checked }
checked = checkedMap[label] ?: false,
onCheckedChange = { checked -> checkedMap[label] = checked },
colors = CheckboxDefaults.colors(
checkedColor = panicColor,
uncheckedColor = Color.DarkGray
)
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = option)
}
}
// Additional notes field — show always (wireframe shows a note field)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = otherNote,
onValueChange = { otherNote = it },
@ -101,7 +136,8 @@ fun MyApp() {
placeholder = { Text("Catatan tambahan ...") },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
.heightIn(min = 56.dp, max = 140.dp),
maxLines = 4
)
Spacer(modifier = Modifier.height(8.dp))
@ -110,7 +146,7 @@ fun MyApp() {
if ((checkedMap["Lainnya"] == true) && otherNote.isBlank()) {
Text(
text = "Catatan wajib jika Anda memilih 'Lainnya'",
color = Color(0xFFB71C1C),
color = panicColor,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(top = 6.dp)
)
@ -118,12 +154,12 @@ fun MyApp() {
}
}
Spacer(modifier = Modifier.height(18.dp))
Spacer(modifier = Modifier.height(20.dp))
// Keep the existing nice PanicButton unchanged
// Keep the existing nice PanicButton unchanged (slightly smaller spacing)
PanicButton(onClick = {
// Validation: at least one option selected
val selected = reportOptions.filter { checkedMap[it] == true }
val selected = reportOptions.map { it.first }.filter { checkedMap[it] == true }
if (selected.isEmpty()) {
dialogMessage = "Pilih minimal satu jenis laporan sebelum mengirim."
return@PanicButton
@ -139,15 +175,15 @@ fun MyApp() {
append(selected.joinToString(", "))
append("\n")
append("Keterangan: ")
if (selected.contains("Lainnya")) append(otherNote.trim()) else append("-")
if (otherNote.isNotBlank()) append(otherNote.trim()) else append("-")
append("\n")
append("Pengirim: Satrio Putra Wardani 202310715307")
append("Pengirim: Rakha adi saputro 202310715083")
}
sendNotification(message) { response -> dialogMessage = response }
})
Spacer(modifier = Modifier.height(16.dp))
Spacer(modifier = Modifier.height(14.dp))
// dialog hasil
if (dialogMessage != null) {
@ -174,7 +210,7 @@ fun MyApp() {
Box(
modifier = Modifier
.fillMaxWidth()
.background(color = Color(0xFFB71C1C))
.background(color = panicColor)
.padding(vertical = 12.dp),
contentAlignment = Alignment.Center
) {
@ -206,7 +242,7 @@ fun MyApp() {
) {
Button(
onClick = { dialogMessage = null },
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFB71C1C))
colors = ButtonDefaults.buttonColors(containerColor = panicColor)
) {
Text(text = "OK", color = Color.White)
}
@ -333,4 +369,4 @@ fun sendNotification(message: String, onResult: (String) -> Unit) {
onResult("Error: ${e.message}")
}
}.start()
}
}