package com.example.barokahstore.ui.screens import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* 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.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import android.content.ClipData import android.widget.Toast import android.content.ClipboardManager import android.content.Context import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontFamily import com.example.barokahstore.data.Category import com.example.barokahstore.data.CsvHelper import com.example.barokahstore.data.DatabaseHelper import com.example.barokahstore.data.Product import com.example.barokahstore.data.User import com.example.barokahstore.ui.components.BarcodeScannerView @OptIn(ExperimentalMaterial3Api::class) @Composable fun StokScreen( dbHelper: DatabaseHelper, currentUser: User ) { val isAdmin = currentUser.role == "admin" var selectedTab by remember { mutableStateOf(0) } // 0: Produk, 1: Kategori var activeCategoryFilter by remember { mutableStateOf(null) } val tabs = listOf("Produk", "Kategori") Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { TabRow( selectedTabIndex = selectedTab, containerColor = Color.Transparent, contentColor = Color(0xFF4F46E5) ) { tabs.forEachIndexed { index, title -> Tab( selected = selectedTab == index, onClick = { selectedTab = index }, text = { Text(title, fontWeight = FontWeight.Bold, fontSize = 14.sp) } ) } } if (selectedTab == 0) { ProdukTabContent( dbHelper = dbHelper, isAdmin = isAdmin, activeCategoryFilter = activeCategoryFilter, onClearCategoryFilter = { activeCategoryFilter = null } ) } else { KategoriTabContent( dbHelper = dbHelper, isAdmin = isAdmin, onCategoryClick = { cat -> activeCategoryFilter = cat selectedTab = 0 // Switch to Produk tab } ) } } } // --- PRODUK TAB CONTENT --- @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable fun ProdukTabContent( dbHelper: DatabaseHelper, isAdmin: Boolean, activeCategoryFilter: Category?, onClearCategoryFilter: () -> Unit ) { var searchQuery by remember { mutableStateOf("") } var productsList by remember { mutableStateOf(listOf()) } var categoriesList by remember { mutableStateOf(listOf()) } val context = LocalContext.current // Dialog States var showAddEditDialog by remember { mutableStateOf(false) } var editingProduct by remember { mutableStateOf(null) } // null for Add, not null for Edit var barcode by remember { mutableStateOf("") } var name by remember { mutableStateOf("") } var buyPriceText by remember { mutableStateOf("") } var sellPriceText by remember { mutableStateOf("") } var stockText by remember { mutableStateOf("") } var unit by remember { mutableStateOf("Pcs") } var selectedCategoryId by remember { mutableStateOf(null) } var alertMessage by remember { mutableStateOf("") } // New States var showCameraInDialog by remember { mutableStateOf(false) } var showSearchCamera by remember { mutableStateOf(false) } val createCsvTemplateLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.CreateDocument("text/csv"), onResult = { uri -> if (uri != null) { try { context.contentResolver.openOutputStream(uri)?.use { outputStream -> val template = CsvHelper.generateCsvTemplate() outputStream.write(template.toByteArray()) } Toast.makeText(context, "Template CSV berhasil diunduh!", Toast.LENGTH_SHORT).show() } catch (e: Exception) { e.printStackTrace() Toast.makeText(context, "Gagal mengunduh template: ${e.message}", Toast.LENGTH_SHORT).show() } } } ) val barcodeFocusRequester = remember { FocusRequester() } LaunchedEffect(showAddEditDialog) { if (showAddEditDialog) { kotlinx.coroutines.delay(100) barcodeFocusRequester.requestFocus() } } fun refreshProducts() { val allProds = dbHelper.getAllProducts() var filteredList = allProds if (activeCategoryFilter != null) { filteredList = filteredList.filter { it.categoryId == activeCategoryFilter.id } } if (searchQuery.isNotEmpty()) { val cleanQuery = searchQuery.trim().removePrefix("0") filteredList = filteredList.filter { val dbBarcodeClean = it.barcode.trim().removePrefix("0") it.name.contains(searchQuery, ignoreCase = true) || it.barcode.contains(searchQuery) || (cleanQuery.isNotEmpty() && dbBarcodeClean == cleanQuery) } } productsList = filteredList categoriesList = dbHelper.getAllCategories() } val pickCsvLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.GetContent(), onResult = { uri -> if (uri != null) { try { val inputStream = context.contentResolver.openInputStream(uri) if (inputStream != null) { val parsed = CsvHelper.parseCsv(inputStream) var successCount = 0 for (p in parsed) { var catId: Int? = null if (p.categoryName != null) { val existing = dbHelper.getAllCategories().find { it.name.equals(p.categoryName, ignoreCase = true) } if (existing != null) { catId = existing.id } else { dbHelper.insertCategory(p.categoryName) val newCat = dbHelper.getAllCategories().find { it.name.equals(p.categoryName, ignoreCase = true) } catId = newCat?.id } } val success = dbHelper.insertProduct(p.barcode, p.name, p.buyPrice, p.sellPrice, p.stock, p.unit, catId) if (success) { successCount++ } else { // Try updating product if barcode exists val existingProd = dbHelper.getProductByBarcode(p.barcode) if (existingProd != null) { dbHelper.updateProduct(existingProd.id, p.barcode, p.name, p.buyPrice, p.sellPrice, p.stock, p.unit, catId) successCount++ } } } refreshProducts() alertMessage = "Berhasil mengimpor $successCount produk dari CSV!" } } catch (e: Exception) { e.printStackTrace() alertMessage = "Gagal memproses file CSV: ${e.message}" } } } ) var showDeleteDialog by remember { mutableStateOf(false) } var productToDelete by remember { mutableStateOf(null) } LaunchedEffect(searchQuery, activeCategoryFilter) { refreshProducts() } Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(12.dp) ) { // Search & Add Bar Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically ) { OutlinedTextField( value = searchQuery, onValueChange = { searchQuery = it }, placeholder = { Text("Cari produk...") }, leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) }, trailingIcon = { IconButton(onClick = { showSearchCamera = !showSearchCamera }) { Icon( imageVector = if (showSearchCamera) Icons.Default.Close else Icons.Default.PlayArrow, contentDescription = "Scan Barcode", tint = Color(0xFF4F46E5) ) } }, singleLine = true, shape = RoundedCornerShape(12.dp), modifier = Modifier.weight(1f) ) if (isAdmin) { Button( onClick = { editingProduct = null barcode = "" name = "" buyPriceText = "" sellPriceText = "" stockText = "" unit = "Pcs" selectedCategoryId = categoriesList.firstOrNull()?.id alertMessage = "" showCameraInDialog = false showAddEditDialog = true }, colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF4F46E5)), shape = RoundedCornerShape(12.dp), modifier = Modifier.height(50.dp) ) { Icon(Icons.Default.Add, contentDescription = null) Spacer(modifier = Modifier.width(4.dp)) Text("Produk") } } } // Live Realtime Camera Scanner Preview for Search if (showSearchCamera) { BarcodeScannerView( onBarcodeScanned = { scannedCode -> searchQuery = scannedCode.trim() showSearchCamera = false }, modifier = Modifier.fillMaxWidth() ) } // CSV Import / Export Actions Row if (isAdmin) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp) ) { Button( onClick = { pickCsvLauncher.launch("text/*") }, colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF059669)), shape = RoundedCornerShape(10.dp), modifier = Modifier.weight(1f).height(45.dp) ) { Icon(Icons.Default.PlayArrow, contentDescription = null) Spacer(modifier = Modifier.width(4.dp)) Text("Impor CSV", fontSize = 12.sp, fontWeight = FontWeight.Bold) } Button( onClick = { createCsvTemplateLauncher.launch("produk_template.csv") }, colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFD97706)), shape = RoundedCornerShape(10.dp), modifier = Modifier.weight(1f).height(45.dp) ) { Icon(Icons.Default.Info, contentDescription = null) Spacer(modifier = Modifier.width(4.dp)) Text("Template CSV", fontSize = 12.sp, fontWeight = FontWeight.Bold) } } } // Active Category Filter Indicator if (activeCategoryFilter != null) { Row( modifier = Modifier .fillMaxWidth() .background(Color(0xFFEEF2FF), RoundedCornerShape(8.dp)) .padding(horizontal = 12.dp, vertical = 6.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Text( text = "Menampilkan Kategori: ${activeCategoryFilter.name}", color = Color(0xFF4F46E5), fontWeight = FontWeight.Bold, fontSize = 12.sp ) IconButton( onClick = onClearCategoryFilter, modifier = Modifier.size(24.dp) ) { Icon( imageVector = Icons.Default.Close, contentDescription = "Hapus filter", tint = Color(0xFF4F46E5), modifier = Modifier.size(16.dp) ) } } } // List Card( modifier = Modifier .fillMaxWidth() .weight(1f), shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { if (productsList.isEmpty()) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text("Produk tidak ditemukan", color = Color.Gray, fontSize = 14.sp) } } else { LazyColumn(modifier = Modifier.padding(16.dp)) { items(productsList) { product -> Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 8.dp) .border(0.5.dp, Color(0xFFE5E7EB), RoundedCornerShape(10.dp)) .padding(12.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column(modifier = Modifier.weight(1f)) { Text(product.name, fontWeight = FontWeight.Bold, fontSize = 14.sp) Text("Barcode: ${product.barcode} • Kategori: ${product.categoryName ?: "-"}", fontSize = 11.sp, color = Color.Gray) Row( modifier = Modifier.padding(top = 4.dp), horizontalArrangement = Arrangement.spacedBy(12.dp) ) { Text("Beli: ${formatRupiah(product.buyPrice)}", fontSize = 12.sp, color = Color.Gray) Text("Jual: ${formatRupiah(product.sellPrice)}", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color(0xFF4F46E5)) } } Column(horizontalAlignment = Alignment.End, verticalArrangement = Arrangement.spacedBy(8.dp)) { Surface( color = if (product.stock <= 10) Color(0xFFFEE2E2) else Color(0xFFD1FAE5), shape = RoundedCornerShape(6.dp) ) { Text( text = "Stok: ${product.stock} ${product.unit}", color = if (product.stock <= 10) Color(0xFFDC2626) else Color(0xFF059669), fontSize = 12.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp) ) } if (isAdmin) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { IconButton( onClick = { editingProduct = product barcode = product.barcode name = product.name buyPriceText = product.buyPrice.toInt().toString() sellPriceText = product.sellPrice.toInt().toString() stockText = product.stock.toString() unit = product.unit selectedCategoryId = product.categoryId alertMessage = "" showAddEditDialog = true }, modifier = Modifier.size(24.dp) ) { Icon(Icons.Default.Edit, contentDescription = null, tint = Color(0xFF3B82F6)) } IconButton( onClick = { productToDelete = product showDeleteDialog = true }, modifier = Modifier.size(24.dp) ) { Icon(Icons.Default.Delete, contentDescription = null, tint = Color(0xFFEF4444)) } } } } } } } } } } // --- ADD / EDIT PRODUCT DIALOG --- if (showAddEditDialog) { Dialog(onDismissRequest = { showAddEditDialog = false }) { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), modifier = Modifier .fillMaxWidth() .padding(16.dp) ) { LazyColumn( modifier = Modifier.padding(24.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { item { Text( text = if (editingProduct == null) "Tambah Produk" else "Edit Produk", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1F2937), modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center ) } if (alertMessage.isNotEmpty()) { item { Text(alertMessage, color = Color.Red, fontSize = 13.sp) } } item { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { OutlinedTextField( value = barcode, onValueChange = { barcode = it }, label = { Text("Barcode") }, singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier .weight(1f) .focusRequester(barcodeFocusRequester) ) Button( onClick = { showCameraInDialog = !showCameraInDialog }, colors = ButtonDefaults.buttonColors( containerColor = if (showCameraInDialog) Color.Red else Color(0xFF4F46E5) ), shape = RoundedCornerShape(10.dp), modifier = Modifier.height(55.dp) ) { Icon( imageVector = if (showCameraInDialog) Icons.Default.Close else Icons.Default.PlayArrow, contentDescription = null ) } } } if (showCameraInDialog) { item { BarcodeScannerView( onBarcodeScanned = { code -> barcode = code showCameraInDialog = false barcodeFocusRequester.requestFocus() }, modifier = Modifier.fillMaxWidth() ) } } item { OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Nama Produk") }, singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.fillMaxWidth() ) } item { OutlinedTextField( value = buyPriceText, onValueChange = { buyPriceText = it }, label = { Text("Harga Beli (Rp)") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.fillMaxWidth() ) } item { OutlinedTextField( value = sellPriceText, onValueChange = { sellPriceText = it }, label = { Text("Harga Jual (Rp)") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.fillMaxWidth() ) } item { Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { OutlinedTextField( value = stockText, onValueChange = { stockText = it }, label = { Text("Stok") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.weight(1f) ) OutlinedTextField( value = unit, onValueChange = { unit = it }, label = { Text("Satuan") }, singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.weight(1f) ) } } // Category dropdown selection item { var dropdownExpanded by remember { mutableStateOf(false) } val selectedCatName = categoriesList.find { it.id == selectedCategoryId }?.name ?: "Pilih Kategori" Text("Kategori Produk", fontSize = 12.sp, color = Color.Gray) Box(modifier = Modifier.fillMaxWidth()) { OutlinedTextField( value = selectedCatName, onValueChange = {}, readOnly = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.fillMaxWidth().clickable { dropdownExpanded = true }, trailingIcon = { IconButton(onClick = { dropdownExpanded = true }) { Icon(Icons.Default.ArrowDropDown, contentDescription = null) } } ) DropdownMenu( expanded = dropdownExpanded, onDismissRequest = { dropdownExpanded = false }, modifier = Modifier.fillMaxWidth() ) { categoriesList.forEach { cat -> DropdownMenuItem( text = { Text(cat.name) }, onClick = { selectedCategoryId = cat.id dropdownExpanded = false } ) } } } } item { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp) ) { OutlinedButton( onClick = { showAddEditDialog = false }, modifier = Modifier.weight(1f) ) { Text("Batal") } Button( onClick = { if (barcode.isBlank() || name.isBlank() || buyPriceText.isBlank() || sellPriceText.isBlank() || stockText.isBlank() || unit.isBlank()) { alertMessage = "Semua kolom harus diisi!" return@Button } val buyP = buyPriceText.toDoubleOrNull() ?: 0.0 val sellP = sellPriceText.toDoubleOrNull() ?: 0.0 val stk = stockText.toIntOrNull() ?: 0 val success: Boolean if (editingProduct == null) { // Check unique barcode if (dbHelper.getProductByBarcode(barcode.trim()) != null) { alertMessage = "Barcode sudah terdaftar!" return@Button } success = dbHelper.insertProduct(barcode.trim(), name.trim(), buyP, sellP, stk, unit.trim(), selectedCategoryId) } else { success = dbHelper.updateProduct(editingProduct!!.id, barcode.trim(), name.trim(), buyP, sellP, stk, unit.trim(), selectedCategoryId) } if (success) { refreshProducts() showAddEditDialog = false } else { alertMessage = "Gagal menyimpan produk!" } }, colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF4F46E5)), modifier = Modifier.weight(1f) ) { Text("Simpan") } } } } } } } // --- DELETE PRODUCT CONFIRM --- if (showDeleteDialog && productToDelete != null) { AlertDialog( onDismissRequest = { showDeleteDialog = false }, title = { Text("Hapus Produk") }, text = { Text("Apakah Anda yakin ingin menghapus produk '${productToDelete!!.name}'?") }, confirmButton = { Button( onClick = { dbHelper.deleteProduct(productToDelete!!.id) refreshProducts() showDeleteDialog = false }, colors = ButtonDefaults.buttonColors(containerColor = Color.Red) ) { Text("Hapus", color = Color.White) } }, dismissButton = { TextButton(onClick = { showDeleteDialog = false }) { Text("Batal") } } ) } } // --- KATEGORI TAB CONTENT --- @OptIn(ExperimentalMaterial3Api::class) @Composable fun KategoriTabContent( dbHelper: DatabaseHelper, isAdmin: Boolean, onCategoryClick: (Category) -> Unit ) { var categoriesList by remember { mutableStateOf(listOf()) } // Add/Edit Dialog var showDialog by remember { mutableStateOf(false) } var editingCategory by remember { mutableStateOf(null) } var categoryName by remember { mutableStateOf("") } var alertMessage by remember { mutableStateOf("") } var showDeleteDialog by remember { mutableStateOf(false) } var categoryToDelete by remember { mutableStateOf(null) } fun refreshCategories() { categoriesList = dbHelper.getAllCategories() } LaunchedEffect(Unit) { refreshCategories() } Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(12.dp) ) { if (isAdmin) { Button( onClick = { editingCategory = null categoryName = "" alertMessage = "" showDialog = true }, colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF4F46E5)), shape = RoundedCornerShape(12.dp), modifier = Modifier .align(Alignment.End) .height(45.dp) ) { Icon(Icons.Default.Add, contentDescription = null) Spacer(modifier = Modifier.width(4.dp)) Text("Kategori") } } Card( modifier = Modifier .fillMaxWidth() .weight(1f), shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { LazyColumn(modifier = Modifier.padding(16.dp)) { items(categoriesList) { category -> Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 6.dp) .border(0.5.dp, Color(0xFFE5E7EB), RoundedCornerShape(10.dp)) .clickable { onCategoryClick(category) } .padding(12.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row(verticalAlignment = Alignment.CenterVertically) { Text(category.name, fontWeight = FontWeight.Bold, fontSize = 14.sp) Spacer(modifier = Modifier.width(6.dp)) Icon( imageVector = Icons.Default.KeyboardArrowRight, contentDescription = "Lihat Produk", tint = Color.LightGray, modifier = Modifier.size(16.dp) ) } if (isAdmin) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { IconButton( onClick = { editingCategory = category categoryName = category.name alertMessage = "" showDialog = true }, modifier = Modifier.size(24.dp) ) { Icon(Icons.Default.Edit, contentDescription = null, tint = Color(0xFF3B82F6)) } IconButton( onClick = { categoryToDelete = category showDeleteDialog = true }, modifier = Modifier.size(24.dp) ) { Icon(Icons.Default.Delete, contentDescription = null, tint = Color(0xFFEF4444)) } } } } } } } } // --- ADD / EDIT KATEGORI DIALOG --- if (showDialog) { Dialog(onDismissRequest = { showDialog = false }) { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), modifier = Modifier .fillMaxWidth() .padding(16.dp) ) { Column( modifier = Modifier.padding(24.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text( text = if (editingCategory == null) "Tambah Kategori" else "Edit Kategori", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1F2937), modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center ) if (alertMessage.isNotEmpty()) { Text(alertMessage, color = Color.Red, fontSize = 13.sp) } OutlinedTextField( value = categoryName, onValueChange = { categoryName = it }, label = { Text("Nama Kategori") }, singleLine = true, shape = RoundedCornerShape(10.dp), modifier = Modifier.fillMaxWidth() ) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp) ) { OutlinedButton( onClick = { showDialog = false }, modifier = Modifier.weight(1f) ) { Text("Batal") } Button( onClick = { if (categoryName.isBlank()) { alertMessage = "Nama kategori tidak boleh kosong!" return@Button } val success = if (editingCategory == null) { dbHelper.insertCategory(categoryName.trim()) } else { dbHelper.updateCategory(editingCategory!!.id, categoryName.trim()) } if (success) { refreshCategories() showDialog = false } else { alertMessage = "Kategori sudah ada atau gagal disimpan!" } }, colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF4F46E5)), modifier = Modifier.weight(1f) ) { Text("Simpan") } } } } } } // --- DELETE KATEGORI CONFIRM --- if (showDeleteDialog && categoryToDelete != null) { AlertDialog( onDismissRequest = { showDeleteDialog = false }, title = { Text("Hapus Kategori") }, text = { Text("Apakah Anda yakin ingin menghapus kategori '${categoryToDelete!!.name}'? Produk dengan kategori ini akan diset tanpa kategori.") }, confirmButton = { Button( onClick = { dbHelper.deleteCategory(categoryToDelete!!.id) refreshCategories() showDeleteDialog = false }, colors = ButtonDefaults.buttonColors(containerColor = Color.Red) ) { Text("Hapus", color = Color.White) } }, dismissButton = { TextButton(onClick = { showDeleteDialog = false }) { Text("Batal") } } ) } }