package com.example.ui.customer 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.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.ArrowForward import androidx.compose.material.icons.filled.DeliveryDining import androidx.compose.material.icons.filled.ElectricBolt import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.LocationOn import androidx.compose.material.icons.filled.Notifications import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.filled.Star import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Surface import androidx.compose.material3.Text 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 java.util.Locale 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.Brush 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.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.example.R import coil.compose.AsyncImage import com.example.data.model.FoodItem import com.example.data.model.OrderStatus import com.example.ui.components.FoodItemImage import com.example.ui.components.QuantityStepper import com.example.ui.components.VegNonVegBadge import com.example.ui.theme.AccentGold import com.example.ui.theme.AccentOrange import com.example.ui.theme.FreshVegGreen import com.example.ui.theme.LoveBlack import com.example.ui.theme.LoveRedDark import com.example.ui.theme.LoveRedPrimary import com.example.ui.theme.TextPrimary import com.example.ui.theme.TextSecondary import com.example.util.ShareAppHelper import com.example.viewmodel.CustomerNavScreen import com.example.viewmodel.CustomerViewModel @Composable fun HomeScreen( customerViewModel: CustomerViewModel, modifier: Modifier = Modifier ) { val context = LocalContext.current val user by customerViewModel.currentUser.collectAsState() val adminSettings by customerViewModel.adminSettings.collectAsState() val allItems by customerViewModel.allFoodItems.collectAsState() val notifications by customerViewModel.allNotifications.collectAsState() val cartItems by customerViewModel.cartItems.collectAsState() val searchQuery by customerViewModel.searchQuery.collectAsState() val allReviews by customerViewModel.allReviews.collectAsState() var selectedDishForReviews by remember { mutableStateOf(null) } var selectedDishForWriteReview by remember { mutableStateOf(null) } val unreadCount = notifications.count { !it.isRead } val bestSellers = allItems.filter { it.isBestSeller } val recommended = allItems.take(6) Box(modifier = modifier.fillMaxSize()) { LazyColumn( modifier = Modifier .fillMaxSize() .background(Color(0xFFF8F9FD)), contentPadding = PaddingValues(bottom = 96.dp) ) { // Top Header matching the user's video at 00:07 & 01:31 item { HomeTopHeader( address = user.address, profileImageUri = user.profileImageUri, unreadCount = unreadCount, onAlertsClick = { customerViewModel.navigateTo(CustomerNavScreen.Alerts) }, onProfileClick = { customerViewModel.navigateTo(CustomerNavScreen.Account) } ) } // Search Bar item { Box( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp) ) { OutlinedTextField( value = searchQuery, onValueChange = { customerViewModel.searchQuery.value = it if (it.isNotBlank()) { customerViewModel.navigateTo(CustomerNavScreen.Menu) } }, placeholder = { Text( text = "Search 'Biryani', 'Burger', 'Maggi'...", color = Color.Gray, fontSize = 14.sp ) }, leadingIcon = { Icon( imageVector = Icons.Default.Search, contentDescription = "Search", tint = LoveRedPrimary ) }, shape = RoundedCornerShape(24.dp), colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color(0xFF1E2022), unfocusedTextColor = Color(0xFF1E2022), focusedContainerColor = Color.White, unfocusedContainerColor = Color.White, cursorColor = LoveRedPrimary, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color(0xFFE2E8F0) ), singleLine = true, modifier = Modifier .fillMaxWidth() .testTag("home_search_input") ) } } // Store Announcement if present if (adminSettings.announcement.isNotBlank()) { item { Surface( color = Color(0xFFFFF3CD), shape = RoundedCornerShape(10.dp), modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 4.dp) ) { Row( modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.ElectricBolt, contentDescription = null, tint = AccentOrange, modifier = Modifier.size(16.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( text = adminSettings.announcement, fontSize = 12.sp, fontWeight = FontWeight.Medium, color = Color(0xFF856404) ) } } } } // Hero Promotional Banner Carousel item { HeroPromotionBanner( onOrderNow = { customerViewModel.navigateTo(CustomerNavScreen.Menu) } ) } // Superfast Food Delivery Restaurant Showcase Card item { RestaurantShowcaseCard( isOpen = adminSettings.isOpen, onExploreMenu = { customerViewModel.navigateTo(CustomerNavScreen.Menu) } ) } // Quick Categories Row item { Text( text = "Quick Categories", fontWeight = FontWeight.Bold, fontSize = 18.sp, color = TextPrimary, modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 8.dp) ) QuickCategoriesRow( onSelectCategory = { cat -> customerViewModel.selectedCategory.value = cat customerViewModel.navigateTo(CustomerNavScreen.Menu) } ) } // Trending Now / Top Selling Items section item { Row( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, top = 20.dp, bottom = 8.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = "🔥 Trending Now", fontWeight = FontWeight.Bold, fontSize = 18.sp, color = TextPrimary ) Spacer(modifier = Modifier.width(6.dp)) Surface( color = LoveRedPrimary, shape = RoundedCornerShape(4.dp) ) { Text( text = "HOT", color = Color.White, fontSize = 10.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp) ) } } Text( text = "See All", color = LoveRedPrimary, fontWeight = FontWeight.Bold, fontSize = 13.sp, modifier = Modifier.clickable { customerViewModel.navigateTo(CustomerNavScreen.Menu) } ) } } // Best Sellers List items(bestSellers) { item -> val qty = cartItems[item.id]?.quantity ?: 0 HomeFoodListItem( item = item, quantity = qty, onAdd = { customerViewModel.addToCart(item) }, onIncrement = { customerViewModel.addToCart(item) }, onDecrement = { customerViewModel.decrementOrRemoveFromCart(item) }, onReviewClick = { selectedDishForReviews = item } ) } } // Ratings & Customer Reviews Bottom Sheet selectedDishForReviews?.let { foodItem -> val dishReviews = allReviews.filter { it.foodItemId == foodItem.id } com.example.ui.components.FoodReviewsBottomSheet( foodItem = foodItem, reviews = dishReviews, onDismiss = { selectedDishForReviews = null }, onWriteReviewClicked = { val target = selectedDishForReviews selectedDishForReviews = null selectedDishForWriteReview = target } ) } // Write Customer Review Dialog selectedDishForWriteReview?.let { foodItem -> com.example.ui.components.WriteReviewDialog( foodItem = foodItem, onDismiss = { selectedDishForWriteReview = null }, onSubmit = { rating, reviewText -> customerViewModel.submitFoodReview(foodItem, rating, reviewText) selectedDishForWriteReview = null } ) } } } @Composable fun HomeTopHeader( address: String, profileImageUri: String, unreadCount: Int, onAlertsClick: () -> Unit, onProfileClick: () -> Unit ) { Surface( color = Color(0xFF1E102E), modifier = Modifier.fillMaxWidth() ) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 14.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.weight(1f) ) { Box( modifier = Modifier .size(36.dp) .background(LoveRedPrimary, CircleShape), contentAlignment = Alignment.Center ) { Image( painter = painterResource(id = R.drawable.logo_love_zone), contentDescription = "Logo", modifier = Modifier .size(32.dp) .clip(CircleShape) ) } Spacer(modifier = Modifier.width(10.dp)) Column { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = "LOVE ZONE", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 15.sp ) Icon( imageVector = Icons.Default.KeyboardArrowDown, contentDescription = null, tint = Color.White, modifier = Modifier.size(18.dp) ) } Text( text = address, color = Color(0xFFCBD5E1), fontSize = 11.sp, maxLines = 1, overflow = TextOverflow.Ellipsis ) } } Row(verticalAlignment = Alignment.CenterVertically) { // Alert Bell with badge Box( modifier = Modifier .clickable(onClick = onAlertsClick) .padding(6.dp) .testTag("home_alert_bell") ) { Icon( imageVector = Icons.Default.Notifications, contentDescription = "Alerts", tint = Color.White, modifier = Modifier.size(24.dp) ) if (unreadCount > 0) { Box( modifier = Modifier .align(Alignment.TopEnd) .size(16.dp) .background(LoveRedPrimary, CircleShape), contentAlignment = Alignment.Center ) { Text( text = "$unreadCount", color = Color.White, fontSize = 9.sp, fontWeight = FontWeight.Bold ) } } } Spacer(modifier = Modifier.width(6.dp)) Box( modifier = Modifier .size(36.dp) .clip(CircleShape) .background(Color.White.copy(alpha = 0.2f)) .clickable(onClick = onProfileClick) .testTag("home_profile_avatar"), contentAlignment = Alignment.Center ) { if (profileImageUri.isNotBlank()) { AsyncImage( model = profileImageUri, contentDescription = "Profile", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop ) } else { Icon( imageVector = Icons.Default.Person, contentDescription = "Profile", tint = Color.White, modifier = Modifier.size(20.dp) ) } } } } } } @Composable fun HeroPromotionBanner(onOrderNow: () -> Unit) { Card( modifier = Modifier .fillMaxWidth() .padding(16.dp) .shadow(6.dp, RoundedCornerShape(18.dp)), shape = RoundedCornerShape(18.dp) ) { Box( modifier = Modifier .fillMaxWidth() .height(160.dp) ) { Image( painter = painterResource(id = R.drawable.img_food_banner), contentDescription = "Banner", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop ) // Gradient Overlay Box( modifier = Modifier .fillMaxSize() .background( Brush.horizontalGradient( colors = listOf( Color.Black.copy(alpha = 0.85f), Color.Black.copy(alpha = 0.4f), Color.Transparent ) ) ) ) Column( modifier = Modifier .fillMaxSize() .padding(16.dp), verticalArrangement = Arrangement.Center ) { Surface( color = AccentGold, shape = RoundedCornerShape(4.dp) ) { Text( text = "WELCOME OFFER", fontWeight = FontWeight.Black, fontSize = 11.sp, color = Color.Black, modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp) ) } Spacer(modifier = Modifier.height(6.dp)) Text( text = "UP TO 50% OFF", fontWeight = FontWeight.Black, fontSize = 22.sp, color = Color.White ) Text( text = "On your first meal order • Use code LOVE50", color = Color(0xFFFFD54F), fontSize = 11.sp, fontWeight = FontWeight.SemiBold ) Spacer(modifier = Modifier.height(10.dp)) Button( onClick = onOrderNow, shape = RoundedCornerShape(20.dp), colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), contentPadding = PaddingValues(horizontal = 16.dp, vertical = 6.dp), modifier = Modifier.height(34.dp).testTag("banner_order_now_button") ) { Text( text = "ORDER NOW", fontSize = 11.sp, fontWeight = FontWeight.Bold ) Spacer(modifier = Modifier.width(4.dp)) Icon( imageVector = Icons.Default.ArrowForward, contentDescription = null, modifier = Modifier.size(14.dp) ) } } } } } @Composable fun RestaurantShowcaseCard( isOpen: Boolean, onExploreMenu: () -> Unit ) { Card( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 4.dp), shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = Color(0xFF221133)), elevation = CardDefaults.cardElevation(defaultElevation = 3.dp) ) { Column(modifier = Modifier.padding(14.dp)) { Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.CenterVertically) { Surface( color = Color(0xFFFF4081), shape = RoundedCornerShape(4.dp) ) { Text( text = "⚡ SUPERFAST FOOD DELIVERY", color = Color.White, fontSize = 10.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp) ) } } Surface( color = if (isOpen) FreshVegGreen else Color.Gray, shape = RoundedCornerShape(4.dp) ) { Text( text = if (isOpen) "OPEN NOW" else "CLOSED", color = Color.White, fontSize = 10.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp) ) } } Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Column(modifier = Modifier.weight(1f)) { Text( text = "Love Zone Restaurant", color = Color.White, fontSize = 18.sp, fontWeight = FontWeight.Bold ) Text( text = "Craving delicious meals? Order freshly cooked specials directly from our kitchen.", color = Color(0xFFD1C4E9), fontSize = 12.sp, lineHeight = 16.sp ) Spacer(modifier = Modifier.height(8.dp)) Row(verticalAlignment = Alignment.CenterVertically) { Surface( color = Color(0xFF311B92), shape = RoundedCornerShape(6.dp) ) { Text( text = "⏱ 20-30 MINS", color = Color.White, fontSize = 11.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp) ) } Spacer(modifier = Modifier.width(8.dp)) Surface( color = Color(0xFF2E7D32), shape = RoundedCornerShape(6.dp) ) { Row( modifier = Modifier.padding(horizontal = 6.dp, vertical = 3.dp), verticalAlignment = Alignment.CenterVertically ) { Icon(Icons.Default.Star, contentDescription = null, tint = Color.White, modifier = Modifier.size(12.dp)) Spacer(modifier = Modifier.width(2.dp)) Text(text = "4.9", color = Color.White, fontSize = 11.sp, fontWeight = FontWeight.Bold) } } } } Spacer(modifier = Modifier.width(12.dp)) Box( modifier = Modifier .size(80.dp) .clip(RoundedCornerShape(12.dp)) .background(LoveBlack) .clickable(onClick = onExploreMenu) ) { Image( painter = painterResource(id = R.drawable.img_special_biryani), contentDescription = "Biryani", modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop ) } } } } } @Composable fun QuickCategoriesRow(onSelectCategory: (String) -> Unit) { val categories = listOf( "All" to "🍽️", "Biryani Special" to "🍗", "Quick Bites" to "🍟", "Starters" to "🍢", "Burgers" to "🍔", "Rolls & Wraps" to "🌯", "Main Course" to "🍛", "Pasta" to "🍝", "Beverages" to "🥤" ) LazyRow( contentPadding = PaddingValues(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(10.dp) ) { items(categories) { (name, emoji) -> Surface( shape = RoundedCornerShape(14.dp), color = Color.White, border = androidx.compose.foundation.BorderStroke(1.dp, Color(0xFFE2E8F0)), modifier = Modifier .clickable { onSelectCategory(name) } .testTag("cat_chip_$name") ) { Row( modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp), verticalAlignment = Alignment.CenterVertically ) { Text(text = emoji, fontSize = 16.sp) Spacer(modifier = Modifier.width(8.dp)) Text( text = name, fontWeight = FontWeight.SemiBold, fontSize = 13.sp, color = TextPrimary ) } } } } } @Composable fun HomeFoodListItem( item: FoodItem, quantity: Int, onAdd: () -> Unit, onIncrement: () -> Unit, onDecrement: () -> Unit, onReviewClick: () -> Unit = {} ) { Card( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 6.dp), shape = RoundedCornerShape(14.dp), colors = CardDefaults.cardColors(containerColor = Color.White), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp) ) { Row( modifier = Modifier .fillMaxWidth() .padding(12.dp), verticalAlignment = Alignment.CenterVertically ) { // Food Image with Veg/Non-Veg badge overlay Box( modifier = Modifier .size(90.dp) .clip(RoundedCornerShape(10.dp)) ) { FoodItemImage( imageUri = item.imageUri, contentDescription = item.name, modifier = Modifier.fillMaxSize() ) VegNonVegBadge( isVeg = item.isVeg, modifier = Modifier .align(Alignment.TopStart) .padding(4.dp) ) } Spacer(modifier = Modifier.width(12.dp)) Column(modifier = Modifier.weight(1f)) { Text( text = item.name, fontWeight = FontWeight.Bold, fontSize = 15.sp, color = TextPrimary, maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( text = item.description, fontSize = 11.sp, color = TextSecondary, maxLines = 2, overflow = TextOverflow.Ellipsis ) Spacer(modifier = Modifier.height(4.dp)) // Rating & Customer Reviews Badge Row( modifier = Modifier .clip(RoundedCornerShape(6.dp)) .background(AccentGold.copy(alpha = 0.12f)) .clickable { onReviewClick() } .padding(horizontal = 6.dp, vertical = 2.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.Star, contentDescription = null, tint = AccentGold, modifier = Modifier.size(12.dp) ) Spacer(modifier = Modifier.width(3.dp)) Text( text = String.format(Locale.getDefault(), "%.1f", item.rating), fontWeight = FontWeight.Bold, fontSize = 11.sp, color = TextPrimary ) Spacer(modifier = Modifier.width(4.dp)) Text( text = "(${item.reviewCount} ratings) >", fontSize = 10.sp, color = LoveRedPrimary, fontWeight = FontWeight.SemiBold ) } Spacer(modifier = Modifier.height(6.dp)) Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth() ) { Row(verticalAlignment = Alignment.CenterVertically) { Text( text = "₹${item.price.toInt()}", fontWeight = FontWeight.Black, fontSize = 16.sp, color = LoveRedPrimary ) Spacer(modifier = Modifier.width(6.dp)) Text( text = "₹${item.originalPrice.toInt()}", fontSize = 12.sp, color = Color.Gray, style = androidx.compose.ui.text.TextStyle( textDecoration = androidx.compose.ui.text.style.TextDecoration.LineThrough ) ) } if (quantity > 0) { QuantityStepper( quantity = quantity, onIncrement = onIncrement, onDecrement = onDecrement ) } else { Button( onClick = onAdd, shape = RoundedCornerShape(8.dp), colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFFFF1F2)), border = androidx.compose.foundation.BorderStroke(1.dp, LoveRedPrimary), contentPadding = PaddingValues(horizontal = 14.dp, vertical = 4.dp), modifier = Modifier .height(32.dp) .testTag("add_item_${item.id}") ) { Text( text = "ADD", color = LoveRedPrimary, fontWeight = FontWeight.Black, fontSize = 12.sp ) } } } } } } }