package com.example.ui.customer.auth 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.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.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowForward import androidx.compose.material.icons.filled.Badge import androidx.compose.material.icons.filled.Cake import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.ContactPhone import androidx.compose.material.icons.filled.Description import androidx.compose.material.icons.filled.Email import androidx.compose.material.icons.filled.ErrorOutline import androidx.compose.material.icons.filled.Fastfood import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.LocationCity import androidx.compose.material.icons.filled.LocationOn import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.filled.Message import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Phone import androidx.compose.material.icons.filled.PinDrop import androidx.compose.material.icons.filled.Restaurant import androidx.compose.material.icons.filled.Security import androidx.compose.material.icons.filled.Speed import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChipDefaults import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults 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.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.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 com.example.R import com.example.ui.theme.AccentGold import com.example.ui.theme.FreshVegGreen import com.example.ui.theme.LoveBlack import com.example.ui.theme.LoveRedPrimary import com.example.ui.theme.TextPrimary import com.example.ui.theme.TextSecondary import com.example.viewmodel.AuthMode import com.example.viewmodel.AuthViewModel @Composable fun AuthContainer( authViewModel: AuthViewModel, onAuthenticated: () -> Unit, modifier: Modifier = Modifier ) { val authMode by authViewModel.authMode.collectAsState() val simulatedSms by authViewModel.simulatedSmsNotice.collectAsState() Box( modifier = modifier .fillMaxSize() .background(Color(0xFFFAFAFA)) ) { Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(bottom = 32.dp) ) { // Simulated SMS Push notification banner showing the dynamic generated OTP AnimatedVisibility(visible = simulatedSms != null) { Surface( color = Color(0xFF1E293B), shape = RoundedCornerShape(12.dp), modifier = Modifier .fillMaxWidth() .padding(16.dp) .shadow(8.dp, RoundedCornerShape(12.dp)) .clickable { authViewModel.autoFillOtp() } .testTag("simulated_sms_banner") ) { Row( modifier = Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier .size(38.dp) .background(LoveRedPrimary, CircleShape), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Message, contentDescription = "SMS", tint = Color.White, modifier = Modifier.size(20.dp) ) } Spacer(modifier = Modifier.width(12.dp)) Column(modifier = Modifier.weight(1f)) { Text( text = "SMS • LOVE-ZONE SECURITY • Just now", color = Color.LightGray, fontSize = 11.sp, fontWeight = FontWeight.Medium ) Text( text = simulatedSms ?: "", color = Color.White, fontSize = 13.sp, fontWeight = FontWeight.SemiBold ) } Spacer(modifier = Modifier.width(8.dp)) Surface( color = LoveRedPrimary, shape = RoundedCornerShape(6.dp), modifier = Modifier.clickable { authViewModel.autoFillOtp() } ) { Text( text = "Auto-fill", color = Color.White, fontSize = 11.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp) ) } } } } when (authMode) { AuthMode.LOGIN -> { LoginScreen( authViewModel = authViewModel, onAuthenticated = onAuthenticated ) } AuthMode.REGISTER -> { RegisterScreen( authViewModel = authViewModel, onAuthenticated = onAuthenticated ) } AuthMode.OTP_VERIFY -> { OtpVerifyScreen( authViewModel = authViewModel, onAuthenticated = onAuthenticated ) } } } } } @Composable fun LoginScreen( authViewModel: AuthViewModel, onAuthenticated: () -> Unit ) { val phone by authViewModel.loginPhone.collectAsState() val errorMessage by authViewModel.errorMessage.collectAsState() Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = 24.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(28.dp)) // Hero Logo Card with glowing effect Box( modifier = Modifier .size(130.dp) .shadow(16.dp, CircleShape, spotColor = LoveRedPrimary) .background(LoveBlack, CircleShape) .border(2.5.dp, LoveRedPrimary, CircleShape), contentAlignment = Alignment.Center ) { Image( painter = painterResource(id = R.drawable.logo_love_zone), contentDescription = "Love Zone Logo", modifier = Modifier .size(120.dp) .clip(CircleShape), contentScale = ContentScale.Fit ) } Spacer(modifier = Modifier.height(16.dp)) Text( text = "LOVE ZONE", fontSize = 24.sp, fontWeight = FontWeight.Black, letterSpacing = 1.sp, color = LoveRedPrimary ) Text( text = "Customer Account Login", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = TextPrimary ) Text( text = "Enter your registered number to access your past orders & delivery status", fontSize = 12.sp, color = TextSecondary, textAlign = TextAlign.Center, modifier = Modifier.padding(horizontal = 16.dp) ) Spacer(modifier = Modifier.height(24.dp)) Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(20.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Column( modifier = Modifier.padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "LOGIN WITH REGISTERED MOBILE", fontWeight = FontWeight.Bold, fontSize = 14.sp, color = TextPrimary ) Text( text = "Each customer has a single verified account for all order history.", fontSize = 12.sp, color = TextSecondary, textAlign = TextAlign.Center, modifier = Modifier.padding(top = 4.dp, bottom = 16.dp) ) // Phone Input with +91 prefix OutlinedTextField( value = phone, onValueChange = { if (it.length <= 10) authViewModel.loginPhone.value = it }, label = { Text("Registered Mobile Number") }, leadingIcon = { Text( text = "+91 ", fontWeight = FontWeight.Bold, color = TextPrimary, modifier = Modifier.padding(start = 12.dp) ) }, trailingIcon = { Icon(imageVector = Icons.Default.Phone, contentDescription = null, tint = LoveRedPrimary) }, singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone), shape = RoundedCornerShape(12.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFE2E8F0) ), modifier = Modifier .fillMaxWidth() .testTag("login_phone_input") ) Spacer(modifier = Modifier.height(16.dp)) OutlinedTextField( value = authViewModel.loginPassword.collectAsState().value, onValueChange = { authViewModel.loginPassword.value = it }, label = { Text("Password") }, leadingIcon = { Icon(imageVector = Icons.Default.Lock, contentDescription = null, tint = LoveRedPrimary) }, visualTransformation = androidx.compose.ui.text.input.PasswordVisualTransformation(), singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), shape = RoundedCornerShape(12.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFE2E8F0) ), modifier = Modifier .fillMaxWidth() .testTag("login_password_input") ) if (errorMessage != null) { Surface( color = Color(0xFFFFEBEE), shape = RoundedCornerShape(8.dp), modifier = Modifier .fillMaxWidth() .padding(top = 10.dp) ) { Row( modifier = Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.ErrorOutline, contentDescription = null, tint = Color.Red, modifier = Modifier.size(18.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( text = errorMessage ?: "", color = Color.Red, fontSize = 12.sp, fontWeight = FontWeight.Medium, modifier = Modifier.weight(1f) ) } } } Spacer(modifier = Modifier.height(18.dp)) Button( onClick = { authViewModel.submitLogin {} }, shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), modifier = Modifier .fillMaxWidth() .height(50.dp) .testTag("login_submit_button") ) { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = "Send Login OTP", fontWeight = FontWeight.Bold, fontSize = 15.sp ) Spacer(modifier = Modifier.width(8.dp)) Icon( imageVector = Icons.AutoMirrored.Filled.ArrowForward, contentDescription = null, modifier = Modifier.size(18.dp) ) } } Spacer(modifier = Modifier.height(14.dp)) // New User Register button OutlinedButton( onClick = { authViewModel.startRegistration() }, shape = RoundedCornerShape(12.dp), modifier = Modifier .fillMaxWidth() .height(46.dp) .testTag("go_to_register_button") ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( imageVector = Icons.Default.Badge, contentDescription = null, tint = LoveRedPrimary, modifier = Modifier.size(16.dp) ) Spacer(modifier = Modifier.width(6.dp)) Text( text = "New Customer? Complete Registration", color = LoveRedPrimary, fontWeight = FontWeight.Bold, fontSize = 13.sp ) } } Spacer(modifier = Modifier.height(10.dp)) TextButton( onClick = { authViewModel.skipAsGuest(onAuthenticated) }, modifier = Modifier.testTag("guest_explore_button") ) { Text( text = "Explore Menu as Guest (Joydip Account)", color = TextSecondary, fontSize = 12.sp ) } } } Spacer(modifier = Modifier.height(28.dp)) TrustBadgesRow() } } /** * Comprehensive Customer Registration Screen * Collects detailed user information so customers experience a complete, verified onboarding. * Strictly prevents duplicate registrations on the same phone number. */ @Composable fun RegisterScreen( authViewModel: AuthViewModel, onAuthenticated: () -> Unit ) { val name by authViewModel.registerName.collectAsState() val phone by authViewModel.registerPhone.collectAsState() val email by authViewModel.registerEmail.collectAsState() val errorMessage by authViewModel.errorMessage.collectAsState() Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = 20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(24.dp)) // Love Zone Official Logo Header Box( modifier = Modifier .size(100.dp) .shadow(12.dp, CircleShape, spotColor = LoveRedPrimary) .background(LoveBlack, CircleShape) .border(2.dp, LoveRedPrimary, CircleShape), contentAlignment = Alignment.Center ) { Image( painter = painterResource(id = R.drawable.logo_love_zone), contentDescription = "Love Zone Logo", modifier = Modifier .size(90.dp) .clip(CircleShape), contentScale = ContentScale.Fit ) } Spacer(modifier = Modifier.height(14.dp)) Text( text = "Fast Account Registration", fontSize = 22.sp, fontWeight = FontWeight.Black, color = TextPrimary ) Text( text = "Enter your details to create a verified account. Delivery address will be collected at order checkout.", fontSize = 12.sp, color = TextSecondary, textAlign = TextAlign.Center, modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp) ) Spacer(modifier = Modifier.height(20.dp)) // Fast Registration Card (Name, Phone, Email ONLY) Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(20.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Column( modifier = Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(14.dp) ) { Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier .size(32.dp) .background(Color(0xFFFFF1F2), CircleShape), contentAlignment = Alignment.Center ) { Icon(Icons.Default.Person, contentDescription = null, tint = LoveRedPrimary, modifier = Modifier.size(18.dp)) } Spacer(modifier = Modifier.width(10.dp)) Column { Text( text = "STEP 1: USER REGISTRATION", fontWeight = FontWeight.Bold, fontSize = 13.sp, color = LoveRedPrimary, letterSpacing = 0.5.sp ) Text( text = "Name, Mobile Number & Email", fontSize = 11.sp, color = TextSecondary ) } } HorizontalDivider(color = Color(0xFFF1F5F9)) // 1. Full Name OutlinedTextField( value = name, onValueChange = { authViewModel.registerName.value = it }, label = { Text("Full Name *") }, placeholder = { Text("e.g. Joydip Debnath") }, leadingIcon = { Icon(Icons.Default.Person, contentDescription = null, tint = LoveRedPrimary) }, singleLine = true, shape = RoundedCornerShape(12.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("register_name_input") ) // 2. Mobile Number OutlinedTextField( value = phone, onValueChange = { if (it.length <= 10) authViewModel.registerPhone.value = it }, label = { Text("Mobile Number *") }, placeholder = { Text("10-digit number") }, leadingIcon = { Text( text = "+91 ", fontWeight = FontWeight.Bold, color = TextPrimary, modifier = Modifier.padding(start = 12.dp) ) }, trailingIcon = { Icon(Icons.Default.Phone, contentDescription = null, tint = LoveRedPrimary) }, singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone), shape = RoundedCornerShape(12.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("register_phone_input") ) // 3. Email Address OutlinedTextField( value = email, onValueChange = { authViewModel.registerEmail.value = it }, label = { Text("Email Address *") }, placeholder = { Text("name@example.com") }, leadingIcon = { Icon(Icons.Default.Email, contentDescription = null, tint = LoveRedPrimary) }, singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email), shape = RoundedCornerShape(12.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("register_email_input") ) // 4. Password OutlinedTextField( value = authViewModel.registerPassword.collectAsState().value, onValueChange = { authViewModel.registerPassword.value = it }, label = { Text("Set Password *") }, placeholder = { Text("Min 6 characters") }, leadingIcon = { Icon(Icons.Default.Lock, contentDescription = null, tint = LoveRedPrimary) }, visualTransformation = androidx.compose.ui.text.input.PasswordVisualTransformation(), singleLine = true, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), shape = RoundedCornerShape(12.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("register_password_input") ) if (errorMessage != null) { Surface( color = Color(0xFFFFEBEE), shape = RoundedCornerShape(8.dp), modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.ErrorOutline, contentDescription = null, tint = Color.Red, modifier = Modifier.size(18.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( text = errorMessage ?: "", color = Color.Red, fontSize = 12.sp, fontWeight = FontWeight.Medium, modifier = Modifier.weight(1f) ) } } } Spacer(modifier = Modifier.height(6.dp)) // Submit & Send OTP Button (Step 1 -> Step 2 OTP Submission) Button( onClick = { authViewModel.submitRegistration {} }, shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), modifier = Modifier .fillMaxWidth() .height(50.dp) .testTag("register_submit_button") ) { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = "Submit & Get OTP (Step 2)", fontWeight = FontWeight.Bold, fontSize = 15.sp ) Spacer(modifier = Modifier.width(8.dp)) Icon(Icons.AutoMirrored.Filled.ArrowForward, contentDescription = null, modifier = Modifier.size(18.dp)) } } } } Spacer(modifier = Modifier.height(18.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Already registered? ", fontSize = 13.sp, color = TextSecondary ) Text( text = "Login with Mobile", fontSize = 13.sp, fontWeight = FontWeight.Bold, color = LoveRedPrimary, modifier = Modifier .clickable { authViewModel.startLogin() } .padding(4.dp) .testTag("back_to_login_button") ) } Spacer(modifier = Modifier.height(24.dp)) TrustBadgesRow() } } /** * Dynamic, Single-Use OTP Verification Screen * Ensures a fresh 6-digit code is verified each time. */ @Composable fun OtpVerifyScreen( authViewModel: AuthViewModel, onAuthenticated: () -> Unit ) { val enteredOtp by authViewModel.enteredOtp.collectAsState() val timerSeconds by authViewModel.otpTimerSeconds.collectAsState() val isTimerActive by authViewModel.isTimerActive.collectAsState() val errorMessage by authViewModel.errorMessage.collectAsState() Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = 24.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Spacer(modifier = Modifier.height(30.dp)) // Lock Icon badge Box( modifier = Modifier .size(72.dp) .background(Color(0xFFFFF1F2), CircleShape) .border(2.dp, LoveRedPrimary, CircleShape), contentAlignment = Alignment.Center ) { Icon( imageVector = Icons.Default.Lock, contentDescription = "Lock", tint = LoveRedPrimary, modifier = Modifier.size(36.dp) ) } Spacer(modifier = Modifier.height(18.dp)) Text( text = "VERIFY MOBILE OTP", fontSize = 22.sp, fontWeight = FontWeight.Black, color = TextPrimary ) Text( text = "Enter the 6-digit dynamic code sent via SMS to verify your mobile number", fontSize = 13.sp, color = TextSecondary, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(24.dp)) Card( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(20.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) ) { Column( modifier = Modifier.padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { // 6 Boxes OTP Visualizer Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly ) { for (i in 0 until 6) { val char = if (i < enteredOtp.length) enteredOtp[i].toString() else "" Box( modifier = Modifier .size(46.dp) .border( width = if (i == enteredOtp.length) 2.dp else 1.dp, color = if (i == enteredOtp.length) LoveRedPrimary else Color(0xFFCBD5E1), shape = RoundedCornerShape(10.dp) ) .background(Color(0xFFF8FAFC), RoundedCornerShape(10.dp)), contentAlignment = Alignment.Center ) { Text( text = char, fontSize = 20.sp, fontWeight = FontWeight.Bold, color = TextPrimary ) } } } Spacer(modifier = Modifier.height(16.dp)) // Actual input field OutlinedTextField( value = enteredOtp, onValueChange = { if (it.length <= 6 && it.all { c -> c.isDigit() }) { authViewModel.enteredOtp.value = it } }, label = { Text("Enter 6-digit OTP") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword), singleLine = true, shape = RoundedCornerShape(12.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color(0xFFF8FAFC), cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFE2E8F0) ), modifier = Modifier .fillMaxWidth() .testTag("otp_input_field") ) if (errorMessage != null) { Surface( color = Color(0xFFFFEBEE), shape = RoundedCornerShape(8.dp), modifier = Modifier .fillMaxWidth() .padding(top = 10.dp) ) { Row( modifier = Modifier.padding(10.dp), verticalAlignment = Alignment.CenterVertically ) { Icon(Icons.Default.ErrorOutline, contentDescription = null, tint = Color.Red, modifier = Modifier.size(16.dp)) Spacer(modifier = Modifier.width(6.dp)) Text( text = errorMessage ?: "", color = Color.Red, fontSize = 12.sp, modifier = Modifier.weight(1f) ) } } } Spacer(modifier = Modifier.height(20.dp)) Button( onClick = { authViewModel.verifyOtp(onSuccess = onAuthenticated) }, shape = RoundedCornerShape(12.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), modifier = Modifier .fillMaxWidth() .height(50.dp) .testTag("verify_otp_button") ) { Row(verticalAlignment = Alignment.CenterVertically) { Icon(imageVector = Icons.Default.CheckCircle, contentDescription = null, modifier = Modifier.size(18.dp)) Spacer(modifier = Modifier.width(8.dp)) Text(text = "Verify OTP & Continue", fontWeight = FontWeight.Bold, fontSize = 15.sp) } } Spacer(modifier = Modifier.height(16.dp)) Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { if (isTimerActive) { Text( text = "OTP expires in ${timerSeconds}s", fontSize = 12.sp, color = TextSecondary, fontWeight = FontWeight.Medium ) } else { Text( text = "Didn't receive the OTP? ", fontSize = 12.sp, color = TextSecondary ) Text( text = "Resend Fresh OTP", fontSize = 12.sp, fontWeight = FontWeight.Bold, color = LoveRedPrimary, modifier = Modifier .clickable { authViewModel.resendOtp() } .padding(4.dp) .testTag("resend_otp_button") ) } } Spacer(modifier = Modifier.height(10.dp)) TextButton( onClick = { authViewModel.startLogin() }, modifier = Modifier.testTag("change_phone_number_button") ) { Text(text = "Change Mobile Number / Cancel", color = TextSecondary, fontSize = 12.sp) } } } Spacer(modifier = Modifier.height(28.dp)) TrustBadgesRow() } } @Composable fun TrustBadgesRow() { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 8.dp), horizontalArrangement = Arrangement.SpaceAround ) { TrustBadgeItem( icon = Icons.Default.Security, title = "100% Safe", subtitle = "Single Verified ID", color = FreshVegGreen ) TrustBadgeItem( icon = Icons.Default.CheckCircle, title = "Best Quality", subtitle = "Kumarghat Fresh", color = AccentGold ) TrustBadgeItem( icon = Icons.Default.Speed, title = "On-Time", subtitle = "Fast Delivery", color = LoveRedPrimary ) } } @Composable fun TrustBadgeItem( icon: androidx.compose.ui.graphics.vector.ImageVector, title: String, subtitle: String, color: Color ) { Column(horizontalAlignment = Alignment.CenterHorizontally) { Box( modifier = Modifier .size(36.dp) .background(color.copy(alpha = 0.15f), CircleShape), contentAlignment = Alignment.Center ) { Icon( imageVector = icon, contentDescription = null, tint = color, modifier = Modifier.size(18.dp) ) } Spacer(modifier = Modifier.height(4.dp)) Text(text = title, fontSize = 11.sp, fontWeight = FontWeight.Bold, color = TextPrimary) Text(text = subtitle, fontSize = 9.sp, color = TextSecondary) } }