"Otomatis" -> { Text( text = "Pemantauan sensor", fontSize = 15.sp, fontFamily = Inria_Regular, color = Color.Gray, modifier = Modifier .align(Alignment.Start) .padding(horizontal = 28.dp) ) Spacer(modifier = Modifier.height(15.dp)) Card( modifier = Modifier .padding(horizontal = 25.dp) .size(width = 333.dp, height = 130.dp), shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFFEDEDED) ) ) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { // ================== KELEMBABAN UDARA ================== Column( modifier = Modifier.padding(top = 15.dp, start = 19.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { Box( contentAlignment = Alignment.Center, modifier = Modifier.size(60.dp) ) { CircularProgressIndicator( progress = 1f, color = Color.LightGray, strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) CircularProgressIndicator( progress = progressKU, color = Color(0xFF4FC3F7), strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) Text( text = "$ku%", fontSize = 14.sp, fontWeight = FontWeight.Bold ) } Text("Kel. Udara", fontSize = 10.sp, fontWeight = FontWeight.Bold) Text( text = statusKelembaban(ku), fontSize = 10.sp, fontWeight = FontWeight.Bold, color = Color.Gray, modifier = Modifier.offset(y = -8.dp, x = 10.dp) ) } // ================== SUHU UDARA ================== Column( modifier = Modifier.padding(top = 15.dp, start = 10.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { Box( contentAlignment = Alignment.Center, modifier = Modifier.size(60.dp) ) { CircularProgressIndicator( progress = 1f, color = Color.LightGray, strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) CircularProgressIndicator( progress = progressSU, color = Color(0xFF4FC3F7), strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) Text( text = "$su°C", fontSize = 14.sp, fontWeight = FontWeight.Bold ) } Text("Suhu Udara", fontSize = 10.sp, fontWeight = FontWeight.Bold) Text( text = statusSuhu(su), fontSize = 10.sp, fontWeight = FontWeight.Bold, color = Color.Gray, modifier = Modifier.offset(y = -8.dp, x = 10.dp) ) } // ================== KELEMBABAN TANAH ================== Column( modifier = Modifier.padding(top = 15.dp, start = 10.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { Box( contentAlignment = Alignment.Center, modifier = Modifier.size(60.dp) ) { CircularProgressIndicator( progress = 1f, color = Color.LightGray, strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) CircularProgressIndicator( progress = progressKT, color = Color(0xFF4FC3F7), strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) Text( text = "$kt%", fontSize = 14.sp, fontWeight = FontWeight.Bold ) } Text("Kel. Tanah", fontSize = 10.sp, fontWeight = FontWeight.Bold) Text( text = statusKelembaban(kt), fontSize = 10.sp, fontWeight = FontWeight.Bold, color = Color.Gray, modifier = Modifier.offset(y = -8.dp, x = 10.dp) ) } // ================== INTENSITAS HUJAN ================== Column( modifier = Modifier.padding(top = 15.dp, start = 10.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { Box( contentAlignment = Alignment.Center, modifier = Modifier.size(60.dp) ) { CircularProgressIndicator( progress = 1f, color = Color.LightGray, strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) CircularProgressIndicator( progress = progressIH, color = Color(0xFF4FC3F7), strokeWidth = 3.dp, modifier = Modifier.fillMaxSize() ) Text( text = "$ih%", fontSize = 14.sp, fontWeight = FontWeight.Bold ) } Text("Int. Hujan", fontSize = 10.sp, fontWeight = FontWeight.Bold) Text( text = when { ih < 40 -> "Ringan" ih < 70 -> "Sedang" else -> "Deras" }, fontSize = 10.sp, fontWeight = FontWeight.Bold, color = Color.Gray, modifier = Modifier.offset(y = -8.dp) ) } } } Spacer(modifier = Modifier.height(15.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start ){ Text( text = "Atur jadwal", fontSize = 15.sp, color = Color.Gray, fontFamily = Inria_Regular, modifier = Modifier .padding(horizontal = 28.dp) ) Image( painter = painterResource(id = R.drawable.calendar), contentDescription = "gambar 1", modifier = Modifier .size(13.dp) .offset(y = 2.dp, x = -20.dp), colorFilter = ColorFilter.tint(Color(0xFF6B6666)) ) } Spacer(modifier = Modifier.height(15.dp)) var jadwalList by remember { mutableStateOf(listOf()) } Card( modifier = Modifier .padding(horizontal = 25.dp) .fillMaxWidth() .height(190.dp), shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFFEDEDED) ), elevation = CardDefaults.cardElevation(4.dp) ) { Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(vertical = 12.dp) ) { // semua jadwal tampil jadwalList.forEachIndexed { index, jadwal -> Column( modifier = Modifier.padding(horizontal = 20.dp) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { // kiri Row( verticalAlignment = Alignment.CenterVertically ) { Image( painter = painterResource(id = R.drawable.trash), contentDescription = "Hapus jadwal", modifier = Modifier .size(14.dp) .clickable { jadwalList = jadwalList.toMutableList().also { it.removeAt(index) } } ) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Jadwal ${index + 1}", fontSize = 12.sp, fontWeight = FontWeight.Bold ) } // kanan edit Image( painter = painterResource(id = R.drawable.edit_text), contentDescription = "Edit jadwal", modifier = Modifier .size(14.dp) .clickable { val timePickerDialog = TimePickerDialog( context, { _, hourOfDay, minute -> val status = getWaktuStatus(hourOfDay, minute) val editedJadwal = String.format( "%02d:%02d %s", hourOfDay, minute, status ) jadwalList = jadwalList.toMutableList().also { it[index] = editedJadwal } }, 0, 0, true ) timePickerDialog.show() } ) } Spacer(modifier = Modifier.height(6.dp)) Text( text = jadwal, fontSize = 12.sp, fontWeight = FontWeight.Bold ) HorizontalDivider( modifier = Modifier.padding(vertical = 10.dp), thickness = 0.8.dp, color = Color.Gray.copy(alpha = 0.3f) ) } } // tombol tambah Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 20.dp) .height(40.dp) .clickable { val timePickerDialog = TimePickerDialog( context, { _, hourOfDay, minute -> val status = getWaktuStatus(hourOfDay, minute) val newJadwal = String.format( "%02d:%02d %s", hourOfDay, minute, status ) jadwalList = jadwalList + newJadwal }, 0, 0, true ) timePickerDialog.show() }, horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Text( text = "+", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = Color(0xFF2F6F4E) ) Spacer(modifier = Modifier.width(6.dp)) Text( text = "Tambah Jadwal", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color(0xFF2F6F4E) ) } } } // popup edit custom if (showEditDialog) { AlertDialog( onDismissRequest = { showEditDialog = false }, title = { Text( text = "Edit Jadwal", fontWeight = FontWeight.Bold ) }, text = { Column { Text( text = "Jadwal saat ini:", fontSize = 12.sp ) Spacer(modifier = Modifier.height(8.dp)) Text( text = selectedTimeText, fontSize = 14.sp, fontWeight = FontWeight.Bold ) } }, confirmButton = { TextButton( onClick = { showEditDialog = false val timePickerDialog = TimePickerDialog( context, { _, hourOfDay, minute -> val status = getWaktuStatus(hourOfDay, minute) selectedTimeText = String.format( "%02d:%02d %s", hourOfDay, minute, status ) }, 0, 0, true ) timePickerDialog.show() } ) { Text("Ubah") } }, dismissButton = { TextButton( onClick = { showEditDialog = false } ) { Text("Batal") } } ) } Spacer(modifier = Modifier.height(15.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start ) { Text( text = "Atur jeda penyiraman", fontSize = 15.sp, fontFamily = Inria_Regular, color = Color.Gray, modifier = Modifier .padding(horizontal = 28.dp) ) Image( painter = painterResource(id = R.drawable.clock), contentDescription = "gambar 1", modifier = Modifier.size(14.dp) .offset(y = 1.dp, x = -20.dp), colorFilter = ColorFilter.tint(Color(0xFF6B6666)) ) } Spacer(modifier = Modifier.height(15.dp)) Card( modifier = Modifier .padding(horizontal = 25.dp) .size(width = 333.dp, height = 110.dp), shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFFEDEDED) ) ) { Column( modifier = Modifier .padding(top = 15.dp) // 🔥 kasih jarak dari atas .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically // 🔥 center! ) { BasicTextField( value = jeda, onValueChange = { if (it.all { char -> char.isDigit() }) { jeda = it.take(2) } }, singleLine = true, textStyle = LocalTextStyle.current.copy( fontSize = 28.sp, // 🔥 lebih besar fontWeight = FontWeight.Bold, fontFamily = Poppins_Black, color = Color.Black.copy(alpha = 0.8f) ), modifier = Modifier.width(60.dp) .offset(x = 4.dp), decorationBox = { innerTextField -> if (jeda.isEmpty()) { Text( "00", fontSize = 28.sp, fontFamily = Poppins_Black, fontWeight = FontWeight.Bold, color = Color.Black.copy(alpha = 0.7f) ) } innerTextField() } ) Box( modifier = Modifier.offset(x = -3.dp) ) { Text( text = selectedUnit, fontSize = 14.sp, // 🔥 sedikit diperbesar fontFamily = Poppins_Regular, fontWeight = FontWeight.Bold, color = Color.Black.copy(alpha = 0.7f), modifier = Modifier .clickable { expanded = true } ) DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { listOf("Detik", "Menit", "Jam").forEach { unit -> DropdownMenuItem( text = { Text(unit) }, onClick = { selectedUnit = unit expanded = false } ) } } } } Spacer(modifier = Modifier.height(13.dp)) // 🔥 jarak tombol Card( modifier = Modifier .fillMaxWidth() .padding(horizontal = 60.dp) .offset(y = -10.dp) .height(42.dp) .scale(scale), onClick = { if (jeda.isEmpty()) { Toast.makeText(context, "Masukkan jeda dulu", Toast.LENGTH_SHORT).show() return@Card } val jedaInt = jeda.toInt() val jedaDalamDetik = when (selectedUnit) { "Detik" -> jedaInt "Menit" -> jedaInt * 60 "Jam" -> jedaInt * 3600 else -> jedaInt } saveJeda(jedaDalamDetik.toString(), context) }, interactionSource = interactionSource, shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFF2F6F4E) ) ) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Text( text = "Simpan", fontSize = 15.sp, color = Color.White, fontFamily = Poppins_Regular, fontWeight = FontWeight.Bold ) } } } } Spacer(modifier = Modifier.height(15.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start ) { Text( text = "Atur ambang batas", fontSize = 15.sp, fontFamily = Inria_Regular, color = Color.Gray, modifier = Modifier .padding(horizontal = 28.dp) ) Image( painter = painterResource(id = R.drawable.warning), contentDescription = "gambar 1", modifier = Modifier.size(14.dp) .offset(y = 1.dp, x = -20.dp), colorFilter = ColorFilter.tint(Color(0xFF6B6666)) ) } Spacer(modifier = Modifier.height(15.dp)) Card( modifier = Modifier .padding(horizontal = 25.dp) .size(width = 333.dp, height = 200.dp), shape = RoundedCornerShape(24.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFFEDEDED) ) ) { Column(modifier = Modifier.fillMaxSize()) { // ================= TANAH ================= Column(modifier = Modifier.padding(top = 15.dp)) { Row( modifier = Modifier .padding(horizontal = 15.dp) .fillMaxWidth() ) { Image( painter = painterResource(id = R.drawable.decagon), contentDescription = null, modifier = Modifier.size(14.dp), colorFilter = ColorFilter.tint(Color(0xFF6B6666)) ) Text( text = "Kelembapan tanah", fontSize = 10.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 10.dp) ) } Row( modifier = Modifier .fillMaxWidth() .padding(start = 39.dp, end = 15.dp, top = 2.dp), horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.Bottom) { Text( text = if (tanah == 0 && !isSavedTanah) "-" else tanah.toString(), fontSize = 20.sp, fontWeight = FontWeight.Bold ) Spacer(modifier = Modifier.width(5.dp)) Text("%") } Row(verticalAlignment = Alignment.CenterVertically) { Text( text = if (isSavedTanah) "Tersimpan" else "Belum diatur", fontSize = 10.sp ) Spacer(modifier = Modifier.width(5.dp)) if (isSavedTanah) { Image( painter = painterResource(id = R.drawable.checked), contentDescription = null, modifier = Modifier.size(13.dp) ) } Spacer(modifier = Modifier.width(5.dp)) Image( painter = painterResource(id = R.drawable.edit_text), contentDescription = "edit", modifier = Modifier .size(13.dp) .clickable { currentField = "tanah" inputValue = tanah.toString() showDialog = true } ) } } } HorizontalDivider(modifier = Modifier.padding(top = 8.dp)) // ================= SUHU ================= Column(modifier = Modifier.padding(top = 8.dp)) { Row( modifier = Modifier .padding(horizontal = 15.dp) .fillMaxWidth() ) { Image( painter = painterResource(id = R.drawable.thermometer), contentDescription = null, modifier = Modifier.size(14.dp) ) Text( text = "Suhu udara", fontSize = 10.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 10.dp) ) } Row( modifier = Modifier .fillMaxWidth() .padding(start = 39.dp, end = 15.dp, top = 2.dp), horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.Bottom) { Text( text = if (suhu == 0 && !isSavedSuhu) "-" else suhu.toString(), fontSize = 20.sp, fontWeight = FontWeight.Bold ) Spacer(modifier = Modifier.width(5.dp)) Text("%") } Row(verticalAlignment = Alignment.CenterVertically) { Text( text = if (isSavedSuhu) "Tersimpan" else "Belum diatur", fontSize = 10.sp ) Spacer(modifier = Modifier.width(5.dp)) if (isSavedSuhu) { Image( painter = painterResource(id = R.drawable.checked), contentDescription = null, modifier = Modifier.size(13.dp) ) } Spacer(modifier = Modifier.width(5.dp)) Image( painter = painterResource(id = R.drawable.edit_text), contentDescription = "edit", modifier = Modifier .size(13.dp) .clickable { currentField = "suhu" inputValue = suhu.toString() showDialog = true } ) } } } HorizontalDivider(modifier = Modifier.padding(top = 8.dp)) // ================= UDARA ================= Column(modifier = Modifier.padding(top = 8.dp)) { Row( modifier = Modifier .padding(horizontal = 15.dp) .fillMaxWidth() ) { Image( painter = painterResource(id = R.drawable.drop), contentDescription = null, modifier = Modifier.size(14.dp) ) Text( text = "Kelembapan udara", fontSize = 10.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 10.dp) ) } Row( modifier = Modifier .fillMaxWidth() .padding(start = 39.dp, end = 15.dp, top = 2.dp), horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.Bottom) { Text( text = if (udara == 0 && !isSavedUdara) "-" else udara.toString(), fontSize = 20.sp, fontWeight = FontWeight.Bold ) Spacer(modifier = Modifier.width(5.dp)) Text("%") } Row(verticalAlignment = Alignment.CenterVertically) { Text( text = if (isSavedUdara) "Tersimpan" else "Belum diatur", fontSize = 10.sp ) Spacer(modifier = Modifier.width(5.dp)) if (isSavedUdara) { Image( painter = painterResource(id = R.drawable.checked), contentDescription = null, modifier = Modifier.size(13.dp) ) } Spacer(modifier = Modifier.width(5.dp)) Image( painter = painterResource(id = R.drawable.edit_text), contentDescription = "edit", modifier = Modifier .size(13.dp) .clickable { currentField = "udara" inputValue = udara.toString() showDialog = true } ) } } } } } if (showDialog) { AlertDialog( onDismissRequest = { showDialog = false }, title = { Text("Atur Nilai") }, text = { OutlinedTextField( value = inputValue, onValueChange = { inputValue = it }, label = { Text("Masukkan angka") } ) }, confirmButton = { TextButton( onClick = { val value = inputValue.toIntOrNull() if (value == null) { Toast.makeText(context, "Masukkan angka!", Toast.LENGTH_SHORT).show() return@TextButton } val newValue = value.coerceIn(0, 100) when (currentField) { "tanah" -> { tanah = newValue isSavedTanah = newValue != 0 } "suhu" -> { suhu = newValue isSavedSuhu = newValue != 0 } "udara" -> { udara = newValue isSavedUdara = newValue != 0 } } scope.launch { try { RetrofitClient.api.saveSetting(1, tanah, suhu, udara) Toast.makeText(context, "Berhasil disimpan", Toast.LENGTH_SHORT).show() } catch (e: Exception) { Toast.makeText(context, "Gagal menyimpan", Toast.LENGTH_SHORT).show() } } showDialog = false } ) { Text("Simpan") } }, dismissButton = { Row { TextButton( onClick = { when (currentField) { "tanah" -> { tanah = 0 isSavedTanah = false } "suhu" -> { suhu = 0 isSavedSuhu = false } "udara" -> { udara = 0 isSavedUdara = false } } scope.launch { try { RetrofitClient.api.saveSetting(1, tanah, suhu, udara) Toast.makeText(context, "Berhasil dihapus", Toast.LENGTH_SHORT).show() } catch (e: Exception) { Toast.makeText(context, "Gagal menghapus", Toast.LENGTH_SHORT).show() } } showDialog = false } ) { Text("Hapus", color = Color.Red) } Spacer(modifier = Modifier.width(8.dp)) TextButton( onClick = { showDialog = false } ) { Text("Batal") } } } ) } Spacer(modifier = Modifier.height(25.dp)) Card( modifier = Modifier .padding(horizontal = 25.dp) .padding(bottom = 15.dp) .fillMaxWidth() .height(50.dp) .scale(scale), // ✅ animasi dari kode kamu onClick = { viewModel.setConfig( jadwal = "08:00", ambang = 60, jeda = 10 ) }, interactionSource = interactionSource, shape = RoundedCornerShape(30.dp), colors = CardDefaults.cardColors( containerColor = Color(0xFF2F6F4E) ), elevation = CardDefaults.cardElevation(4.dp) ) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Text( text = "Simpan", fontSize = 15.sp, color = Color.White, fontFamily = Poppins_Bold, fontWeight = FontWeight.Bold ) } } }