package com.example.ui.customer import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.net.Uri import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.ContentCopy import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.DeliveryDining import androidx.compose.material.icons.filled.Discount import androidx.compose.material.icons.filled.LocationOn import androidx.compose.material.icons.filled.QrCode2 import androidx.compose.material.icons.filled.Receipt import androidx.compose.material.icons.filled.ShoppingCart import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButtonDefaults import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource 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 coil.compose.AsyncImage import coil.request.ImageRequest import com.example.R import com.example.ui.components.QuantityStepper import com.example.ui.components.VegNonVegBadge import com.example.ui.theme.AccentGold import com.example.ui.theme.FreshVegGreen import com.example.ui.theme.LoveRedPrimary import com.example.ui.theme.TextPrimary import com.example.ui.theme.TextSecondary import com.example.ui.customer.auth.AuthContainer import com.example.viewmodel.AuthViewModel import com.example.viewmodel.CustomerNavScreen import com.example.viewmodel.CustomerViewModel @Composable fun CartScreen( customerViewModel: CustomerViewModel, authViewModel: AuthViewModel, modifier: Modifier = Modifier ) { val context = LocalContext.current val user by customerViewModel.currentUser.collectAsState() if (!user.isLoggedIn) { AuthContainer( authViewModel = authViewModel, onAuthenticated = {} ) return } val cartItemsMap by customerViewModel.cartItems.collectAsState() val cartList = cartItemsMap.values.toList() val cartCount by customerViewModel.cartTotalCount.collectAsState() val itemTotal by customerViewModel.cartItemTotal.collectAsState() val deliveryFee by customerViewModel.deliveryFee.collectAsState() val discount by customerViewModel.couponDiscount.collectAsState() val grandTotal by customerViewModel.grandTotal.collectAsState() val adminSettings by customerViewModel.adminSettings.collectAsState() val currentUser by customerViewModel.currentUser.collectAsState() val selectedPayment by customerViewModel.selectedPaymentMethod.collectAsState() val upiUtr by customerViewModel.upiUtrInput.collectAsState() val cookingNote by customerViewModel.cookingInstruction.collectAsState() var couponInput by remember { mutableStateOf("") } var couponFeedback by remember { mutableStateOf(null) } var orderSuccessDialog by remember { mutableStateOf(false) } var showOnlinePaymentModal by remember { mutableStateOf(false) } Column( modifier = modifier .fillMaxSize() .background(Color(0xFFF8F9FD)) ) { // Header Surface( color = Color.White, shadowElevation = 2.dp, modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 8.dp, vertical = 10.dp), verticalAlignment = Alignment.CenterVertically ) { IconButton( onClick = { customerViewModel.navigateTo(CustomerNavScreen.Home) }, modifier = Modifier.testTag("cart_back_button") ) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", tint = TextPrimary ) } Text( text = "My Cart (${cartCount})", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = TextPrimary ) Spacer(modifier = Modifier.weight(1f)) if (cartList.isNotEmpty()) { TextButton( onClick = { customerViewModel.clearCart() }, modifier = Modifier.testTag("clear_cart_button") ) { Text(text = "Clear", color = LoveRedPrimary, fontSize = 13.sp) } } } } if (cartList.isEmpty()) { // Empty Cart state matching video at 00:34 Box( modifier = Modifier .fillMaxSize() .padding(24.dp), contentAlignment = Alignment.Center ) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Box( modifier = Modifier .size(130.dp) .background(Color(0xFFFFF1F2), CircleShape), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.ShoppingCart, contentDescription = "Empty Cart", tint = LoveRedPrimary, modifier = Modifier.size(64.dp) ) } Spacer(modifier = Modifier.height(20.dp)) Text( text = "Your Cart is Empty", fontSize = 20.sp, fontWeight = FontWeight.Bold, color = TextPrimary ) Spacer(modifier = Modifier.height(8.dp)) Text( text = "Good food is always cooking! Go ahead and add some delicious items from our menu.", fontSize = 13.sp, color = TextSecondary, textAlign = TextAlign.Center, modifier = Modifier.padding(horizontal = 24.dp) ) Spacer(modifier = Modifier.height(24.dp)) Button( onClick = { customerViewModel.navigateTo(CustomerNavScreen.Menu) }, shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), modifier = Modifier.testTag("empty_cart_explore_button") ) { Text( text = "EXPLORE MENU", fontWeight = FontWeight.Bold, fontSize = 14.sp ) } } } } else { LazyColumn( modifier = Modifier .weight(1f) .fillMaxWidth(), contentPadding = PaddingValues(16.dp), verticalArrangement = Arrangement.spacedBy(14.dp) ) { // Cart Items Card item { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Text( text = "Ordered Items", fontWeight = FontWeight.Bold, fontSize = 15.sp, color = TextPrimary ) Spacer(modifier = Modifier.height(10.dp)) cartList.forEach { cartItem -> Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 6.dp), verticalAlignment = Alignment.CenterVertically ) { VegNonVegBadge(isVeg = cartItem.item.isVeg) Spacer(modifier = Modifier.width(8.dp)) Column(modifier = Modifier.weight(1f)) { Text( text = cartItem.item.name, fontWeight = FontWeight.SemiBold, fontSize = 14.sp, color = TextPrimary ) Text( text = "₹${cartItem.item.price.toInt()} each", fontSize = 11.sp, color = TextSecondary ) } QuantityStepper( quantity = cartItem.quantity, onIncrement = { customerViewModel.addToCart(cartItem.item) }, onDecrement = { customerViewModel.decrementOrRemoveFromCart(cartItem.item) } ) Spacer(modifier = Modifier.width(10.dp)) Text( text = "₹${cartItem.subtotal.toInt()}", fontWeight = FontWeight.Bold, fontSize = 14.sp, color = TextPrimary ) } HorizontalDivider(color = Color(0xFFF1F5F9)) } } } } // Interactive Delivery Address Form (Collected at Order Time) item { var isEditingAddress by remember { mutableStateOf(currentUser.houseNo.isBlank() || currentUser.address == "Kumarghat, Tripura 799290") } var houseNoInput by remember(currentUser) { mutableStateOf(currentUser.houseNo.ifBlank { "House #12" }) } var streetInput by remember(currentUser) { mutableStateOf(currentUser.streetArea.ifBlank { "Halaimura Road" }) } var landmarkInput by remember(currentUser) { mutableStateOf(currentUser.landmark.ifBlank { "Near Bhairav Thali" }) } Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier .size(36.dp) .background(Color(0xFFFFF1F2), CircleShape), contentAlignment = Alignment.Center ) { Icon(Icons.Default.LocationOn, contentDescription = null, tint = LoveRedPrimary, modifier = Modifier.size(20.dp)) } Spacer(modifier = Modifier.width(10.dp)) Column { Text( text = "Delivery Address (Order Checkout)", fontWeight = FontWeight.Bold, fontSize = 13.sp, color = TextPrimary ) Text( text = "Customer: ${currentUser.name} (${currentUser.phone})", fontSize = 11.sp, color = LoveRedPrimary ) } } TextButton(onClick = { isEditingAddress = !isEditingAddress }) { Text( text = if (isEditingAddress) "Hide" else "Edit Address", color = LoveRedPrimary, fontSize = 12.sp, fontWeight = FontWeight.Bold ) } } if (!isEditingAddress && currentUser.address.isNotBlank()) { Surface( color = Color(0xFFF8FAFC), shape = RoundedCornerShape(10.dp), modifier = Modifier .fillMaxWidth() .padding(top = 8.dp) ) { Column(modifier = Modifier.padding(10.dp)) { Text( text = currentUser.address, fontSize = 12.sp, color = TextPrimary, fontWeight = FontWeight.Medium ) } } } else { Spacer(modifier = Modifier.height(10.dp)) Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { OutlinedTextField( value = houseNoInput, onValueChange = { houseNoInput = it }, label = { Text("House / Flat / Floor No. *") }, placeholder = { Text("e.g. House #14, Ground Floor") }, singleLine = true, shape = RoundedCornerShape(10.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFCBD5E1) ), modifier = Modifier.fillMaxWidth().testTag("checkout_house_input") ) OutlinedTextField( value = streetInput, onValueChange = { streetInput = it }, label = { Text("Street / Road / Colony / Locality *") }, placeholder = { Text("e.g. Halaimura Road") }, singleLine = true, shape = RoundedCornerShape(10.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFCBD5E1) ), modifier = Modifier.fillMaxWidth().testTag("checkout_street_input") ) OutlinedTextField( value = landmarkInput, onValueChange = { landmarkInput = it }, label = { Text("Nearby Famous Landmark *") }, placeholder = { Text("e.g. Near Bhairav Thali Mandir") }, singleLine = true, shape = RoundedCornerShape(10.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFCBD5E1) ), modifier = Modifier.fillMaxWidth().testTag("checkout_landmark_input") ) Button( onClick = { if (houseNoInput.isNotBlank() && streetInput.isNotBlank() && landmarkInput.isNotBlank()) { val fullAddr = "${houseNoInput.trim()}, ${streetInput.trim()}, Near ${landmarkInput.trim()}, Kumarghat, Tripura 799290" customerViewModel.repository.registerOrUpdateUser( name = currentUser.name, phone = currentUser.phone, email = currentUser.email, address = fullAddr ) isEditingAddress = false } }, colors = ButtonDefaults.buttonColors(containerColor = FreshVegGreen), shape = RoundedCornerShape(8.dp), modifier = Modifier.fillMaxWidth().height(40.dp) ) { Text("Save Delivery Address", fontWeight = FontWeight.Bold, fontSize = 12.sp) } } } } } } // Cooking Instructions item { OutlinedTextField( value = cookingNote, onValueChange = { customerViewModel.cookingInstruction.value = it }, placeholder = { Text("Special cooking instructions (e.g. less spicy, extra tissues)", fontSize = 12.sp) }, shape = RoundedCornerShape(12.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color.White, cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFE2E8F0) ), modifier = Modifier .fillMaxWidth() .testTag("cooking_instruction_input") ) } // Coupon Code Box item { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.Discount, contentDescription = null, tint = AccentGold, modifier = Modifier.size(20.dp)) Spacer(modifier = Modifier.width(8.dp)) Text(text = "Apply Coupon Code", fontWeight = FontWeight.Bold, fontSize = 14.sp) } Spacer(modifier = Modifier.height(10.dp)) Row(verticalAlignment = Alignment.CenterVertically) { OutlinedTextField( value = couponInput, onValueChange = { couponInput = it }, placeholder = { Text("Try 'LOVE50'", fontSize = 13.sp) }, singleLine = true, shape = RoundedCornerShape(10.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFCBD5E1) ), modifier = Modifier .weight(1f) .height(48.dp) .testTag("coupon_input") ) Spacer(modifier = Modifier.width(8.dp)) Button( onClick = { val result = customerViewModel.applyCoupon(couponInput) couponFeedback = result }, shape = RoundedCornerShape(10.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), modifier = Modifier.testTag("apply_coupon_button") ) { Text("Apply", fontWeight = FontWeight.Bold, fontSize = 13.sp) } } if (couponFeedback != null) { Text( text = couponFeedback ?: "", color = if (discount > 0) FreshVegGreen else Color.Red, fontSize = 12.sp, fontWeight = FontWeight.Medium, modifier = Modifier.padding(top = 6.dp) ) } } } } // Payment Options Section (Paytm, Google Pay, PhonePe, UPI QR, Cash on Delivery) item { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Text( text = "Choose Payment Option", fontWeight = FontWeight.Bold, fontSize = 15.sp, color = TextPrimary ) Spacer(modifier = Modifier.height(10.dp)) // 1. Paytm Option Row( modifier = Modifier .fillMaxWidth() .clickable { customerViewModel.selectedPaymentMethod.value = "PAYTM" } .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = selectedPayment == "PAYTM", onClick = { customerViewModel.selectedPaymentMethod.value = "PAYTM" }, colors = RadioButtonDefaults.colors(selectedColor = LoveRedPrimary) ) Spacer(modifier = Modifier.width(6.dp)) Surface( color = Color(0xFF00baf2), shape = RoundedCornerShape(6.dp), modifier = Modifier.padding(end = 8.dp) ) { Text( text = "Paytm", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 11.sp, modifier = Modifier.padding(horizontal = 6.dp, vertical = 3.dp) ) } Column(modifier = Modifier.weight(1f)) { Text(text = "Paytm Online Payment", fontWeight = FontWeight.Bold, fontSize = 13.sp) Text(text = "Pay via Paytm Wallet, UPI or NetBanking", fontSize = 11.sp, color = TextSecondary) } } Spacer(modifier = Modifier.height(6.dp)) // 2. Google Pay Option Row( modifier = Modifier .fillMaxWidth() .clickable { customerViewModel.selectedPaymentMethod.value = "GPAY" } .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = selectedPayment == "GPAY", onClick = { customerViewModel.selectedPaymentMethod.value = "GPAY" }, colors = RadioButtonDefaults.colors(selectedColor = LoveRedPrimary) ) Spacer(modifier = Modifier.width(6.dp)) Surface( color = Color(0xFF1a73e8), shape = RoundedCornerShape(6.dp), modifier = Modifier.padding(end = 8.dp) ) { Text( text = "GPay", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 11.sp, modifier = Modifier.padding(horizontal = 6.dp, vertical = 3.dp) ) } Column(modifier = Modifier.weight(1f)) { Text(text = "Google Pay (GPay)", fontWeight = FontWeight.Bold, fontSize = 13.sp) Text(text = "Pay instantly via Google Pay UPI", fontSize = 11.sp, color = TextSecondary) } } Spacer(modifier = Modifier.height(6.dp)) // 3. PhonePe Option Row( modifier = Modifier .fillMaxWidth() .clickable { customerViewModel.selectedPaymentMethod.value = "PHONEPE" } .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = selectedPayment == "PHONEPE", onClick = { customerViewModel.selectedPaymentMethod.value = "PHONEPE" }, colors = RadioButtonDefaults.colors(selectedColor = LoveRedPrimary) ) Spacer(modifier = Modifier.width(6.dp)) Surface( color = Color(0xFF5f259f), shape = RoundedCornerShape(6.dp), modifier = Modifier.padding(end = 8.dp) ) { Text( text = "PhonePe", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 11.sp, modifier = Modifier.padding(horizontal = 6.dp, vertical = 3.dp) ) } Column(modifier = Modifier.weight(1f)) { Text(text = "PhonePe UPI", fontWeight = FontWeight.Bold, fontSize = 13.sp) Text(text = "Pay via PhonePe app securely", fontSize = 11.sp, color = TextSecondary) } } Spacer(modifier = Modifier.height(6.dp)) // 4. UPI QR Option Row( modifier = Modifier .fillMaxWidth() .clickable { customerViewModel.selectedPaymentMethod.value = "UPI_QR" } .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = selectedPayment == "UPI_QR", onClick = { customerViewModel.selectedPaymentMethod.value = "UPI_QR" }, colors = RadioButtonDefaults.colors(selectedColor = LoveRedPrimary) ) Spacer(modifier = Modifier.width(6.dp)) Column { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = "Scan & Pay UPI QR", fontWeight = FontWeight.Bold, fontSize = 13.sp ) Spacer(modifier = Modifier.width(6.dp)) Surface(color = FreshVegGreen, shape = RoundedCornerShape(4.dp)) { Text( text = "RECOMMENDED", color = Color.White, fontSize = 9.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 4.dp, vertical = 2.dp) ) } } Text( text = "Any UPI App (BHIM, Paytm, GPay, PhonePe)", fontSize = 11.sp, color = TextSecondary ) } } // Show QR Code Container if any Online Payment selected AnimatedVisibility(visible = selectedPayment == "PAYTM" || selectedPayment == "GPAY" || selectedPayment == "PHONEPE" || selectedPayment == "UPI_QR") { Column( modifier = Modifier .fillMaxWidth() .padding(top = 10.dp) .background(Color(0xFFF8FAFC), RoundedCornerShape(12.dp)) .border(1.dp, Color(0xFFE2E8F0), RoundedCornerShape(12.dp)) .padding(14.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Scan QR to Pay: ₹${grandTotal.toInt()}", fontWeight = FontWeight.Bold, fontSize = 14.sp, color = LoveRedPrimary ) Spacer(modifier = Modifier.height(10.dp)) // Display Admin's Custom QR Code or default Love Zone QR Box( modifier = Modifier .size(190.dp) .background(Color.White, RoundedCornerShape(12.dp)) .border(2.dp, LoveRedPrimary, RoundedCornerShape(12.dp)) .padding(10.dp), contentAlignment = Alignment.Center ) { if (adminSettings.qrImageUri.isNotBlank()) { AsyncImage( model = ImageRequest.Builder(context) .data( if (adminSettings.qrImageUri.startsWith("content://") || adminSettings.qrImageUri.startsWith("file://")) Uri.parse(adminSettings.qrImageUri) else adminSettings.qrImageUri ) .crossfade(true) .build(), contentDescription = "Custom Payment QR Code", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Fit, error = painterResource(id = R.drawable.qr_lovezone_upi) ) } else { Image( painter = painterResource(id = R.drawable.qr_lovezone_upi), contentDescription = "Love Zone UPI QR", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Fit ) } } Spacer(modifier = Modifier.height(8.dp)) // UPI ID and copy Row( modifier = Modifier .background(Color(0xFFEDE7F6), RoundedCornerShape(8.dp)) .clickable { val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager clipboard.setPrimaryClip(ClipData.newPlainText("UPI ID", adminSettings.upiId)) Toast.makeText(context, "UPI ID copied: ${adminSettings.upiId}", Toast.LENGTH_SHORT).show() } .padding(horizontal = 12.dp, vertical = 6.dp), verticalAlignment = Alignment.CenterVertically ) { Text( text = "UPI ID: ${adminSettings.upiId}", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = Color(0xFF4A148C) ) Spacer(modifier = Modifier.width(6.dp)) Icon( imageVector = Icons.Default.ContentCopy, contentDescription = "Copy", tint = Color(0xFF4A148C), modifier = Modifier.size(14.dp) ) } Spacer(modifier = Modifier.height(10.dp)) // Online payment mandatory verification notice Surface( color = Color(0xFFEFF6FF), shape = RoundedCornerShape(10.dp), border = androidx.compose.foundation.BorderStroke(1.dp, Color(0xFFBFDBFE)), modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { Text(text = "🛡️", fontSize = 16.sp) Spacer(modifier = Modifier.width(8.dp)) Column { Text( text = "Online Payment Verification Required", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = Color(0xFF1E3A8A) ) Text( text = "नीचे दिए गए बटन पर क्लिक करने पर QR कोड और UTR वेरिफिकेशन गेटवे खुलेगा। केवल असली 12-अंकों का UTR स्वीकार किया जाएगा।", fontSize = 10.sp, color = Color(0xFF1E40AF), lineHeight = 14.sp ) } } } } } HorizontalDivider(color = Color(0xFFF1F5F9), modifier = Modifier.padding(vertical = 8.dp)) // 5. Cash On Delivery Option Row( modifier = Modifier .fillMaxWidth() .clickable { customerViewModel.selectedPaymentMethod.value = "CASH_ON_DELIVERY" } .padding(vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = selectedPayment == "CASH_ON_DELIVERY", onClick = { customerViewModel.selectedPaymentMethod.value = "CASH_ON_DELIVERY" }, colors = RadioButtonDefaults.colors(selectedColor = LoveRedPrimary) ) Spacer(modifier = Modifier.width(6.dp)) Surface( color = Color(0xFF2e7d32), shape = RoundedCornerShape(6.dp), modifier = Modifier.padding(end = 8.dp) ) { Text( text = "COD", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 11.sp, modifier = Modifier.padding(horizontal = 6.dp, vertical = 3.dp) ) } Column(modifier = Modifier.weight(1f)) { Text(text = "Cash on Delivery (COD)", fontWeight = FontWeight.Bold, fontSize = 13.sp) Text(text = "Pay cash when rider delivers to your doorstep", fontSize = 11.sp, color = TextSecondary) } } } } } // Bill Details Card item { Card( shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.Receipt, contentDescription = null, tint = LoveRedPrimary, modifier = Modifier.size(18.dp)) Spacer(modifier = Modifier.width(6.dp)) Text(text = "Bill Details", fontWeight = FontWeight.Bold, fontSize = 14.sp) } Spacer(modifier = Modifier.height(10.dp)) BillLine(title = "Item Total", value = "₹${itemTotal.toInt()}") BillLine( title = "Delivery Partner Fee", value = if (deliveryFee == 0.0) "FREE" else "₹${deliveryFee.toInt()}", isFree = deliveryFee == 0.0 ) if (discount > 0) { BillLine( title = "Coupon Discount", value = "-₹${discount.toInt()}", isDiscount = true ) } HorizontalDivider(color = Color(0xFFE2E8F0), modifier = Modifier.padding(vertical = 8.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text(text = "Grand Total", fontWeight = FontWeight.Black, fontSize = 16.sp, color = TextPrimary) Text(text = "₹${grandTotal.toInt()}", fontWeight = FontWeight.Black, fontSize = 18.sp, color = LoveRedPrimary) } } } } item { Spacer(modifier = Modifier.height(60.dp)) } } // Bottom Sticky Checkout Bar Surface( color = Color.White, shadowElevation = 8.dp, modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Column { Text(text = "TOTAL TO PAY", fontSize = 10.sp, color = TextSecondary, fontWeight = FontWeight.Bold) Text(text = "₹${grandTotal.toInt()}", fontSize = 20.sp, fontWeight = FontWeight.Black, color = LoveRedPrimary) } val isOnlinePayment = selectedPayment != "CASH_ON_DELIVERY" Button( onClick = { if (isOnlinePayment) { showOnlinePaymentModal = true } else { customerViewModel.placeOrder { orderSuccessDialog = true } } }, shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), modifier = Modifier .height(50.dp) .testTag("checkout_place_order_button") ) { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = if (isOnlinePayment) "PAY VIA UPI & PLACE ORDER" else "PLACE ORDER (COD)", fontWeight = FontWeight.Bold, fontSize = 14.sp ) Spacer(modifier = Modifier.width(8.dp)) Icon(if (isOnlinePayment) Icons.Default.QrCode2 else Icons.Default.DeliveryDining, contentDescription = null) } } } } } } // Online UPI Payment & Verification Gateway Modal if (showOnlinePaymentModal) { com.example.ui.components.OnlinePaymentGatewayDialog( grandTotal = grandTotal, adminSettings = adminSettings, selectedPaymentMethod = selectedPayment, onDismiss = { showOnlinePaymentModal = false }, isUtrAlreadyUsed = { utr -> customerViewModel.isUtrAlreadyUsed(utr) }, onPaymentVerified = { utr -> showOnlinePaymentModal = false customerViewModel.placeOrder( customPaymentStatus = "CUSTOMER_PAYMENT_RECEIVED", customUpiTxnId = utr ) { orderSuccessDialog = true } } ) } // Success dialog if (orderSuccessDialog) { androidx.compose.material3.AlertDialog( onDismissRequest = { orderSuccessDialog = false customerViewModel.navigateTo(CustomerNavScreen.Orders) }, title = { Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Default.CheckCircle, contentDescription = null, tint = FreshVegGreen, modifier = Modifier.size(28.dp)) Spacer(modifier = Modifier.width(8.dp)) Text("Order Received! 🎉", fontWeight = FontWeight.Bold) } }, text = { Text( "Love Zone Restaurant has received your order. Our chef is preparing your food fresh and hot! You can track live status in the Orders tab.", fontSize = 14.sp ) }, confirmButton = { Button( onClick = { orderSuccessDialog = false customerViewModel.navigateTo(CustomerNavScreen.Orders) }, colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary) ) { Text("Track Order") } } ) } } @Composable fun BillLine( title: String, value: String, isFree: Boolean = false, isDiscount: Boolean = false ) { Row( modifier = Modifier .fillMaxWidth() .padding(vertical = 3.dp), horizontalArrangement = Arrangement.SpaceBetween ) { Text(text = title, fontSize = 13.sp, color = TextSecondary) Text( text = value, fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = when { isFree -> FreshVegGreen isDiscount -> LoveRedPrimary else -> TextPrimary } ) } }