package com.example.ui.components import androidx.compose.foundation.background 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.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.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.RateReview import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.outlined.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.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf 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.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import com.example.data.model.FoodItem import com.example.data.model.FoodReview import com.example.ui.theme.AccentGold 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 java.text.SimpleDateFormat import java.util.Date import java.util.Locale @OptIn(ExperimentalMaterial3Api::class) @Composable fun FoodReviewsBottomSheet( foodItem: FoodItem, reviews: List, onDismiss: () -> Unit, onWriteReviewClicked: () -> Unit ) { val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) ModalBottomSheet( onDismissRequest = onDismiss, sheetState = sheetState, containerColor = Color.White, shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp) ) { Column( modifier = Modifier .fillMaxWidth() .padding(horizontal = 20.dp, vertical = 12.dp) ) { // Header Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column(modifier = Modifier.weight(1f)) { Text( text = foodItem.name, fontSize = 18.sp, fontWeight = FontWeight.Bold, color = TextPrimary ) Spacer(modifier = Modifier.height(4.dp)) Row(verticalAlignment = Alignment.CenterVertically) { Surface( shape = RoundedCornerShape(6.dp), color = AccentGold.copy(alpha = 0.15f) ) { Row( modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.Star, contentDescription = null, tint = AccentGold, modifier = Modifier.size(16.dp) ) Spacer(modifier = Modifier.width(4.dp)) Text( text = String.format(Locale.getDefault(), "%.1f", foodItem.rating), fontWeight = FontWeight.Bold, fontSize = 14.sp, color = TextPrimary ) } } Spacer(modifier = Modifier.width(8.dp)) Text( text = "(${reviews.size} Customer Reviews)", fontSize = 14.sp, color = TextSecondary, fontWeight = FontWeight.Medium ) } } IconButton( onClick = onDismiss, modifier = Modifier.testTag("close_reviews_sheet") ) { Icon( imageVector = Icons.Default.Close, contentDescription = "Close", tint = TextSecondary ) } } Spacer(modifier = Modifier.height(16.dp)) // Action: Write Review Button Button( onClick = onWriteReviewClicked, colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), shape = RoundedCornerShape(12.dp), modifier = Modifier .fillMaxWidth() .height(46.dp) .testTag("write_review_button") ) { Icon( imageVector = Icons.Default.RateReview, contentDescription = null, tint = Color.White, modifier = Modifier.size(18.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( text = "Write a Review for this Dish", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 14.sp ) } Spacer(modifier = Modifier.height(16.dp)) Text( text = "Customer Written Reviews (\"Kya Likh Kar Rating Kiya Hai\"):", fontSize = 14.sp, fontWeight = FontWeight.Bold, color = TextPrimary ) Spacer(modifier = Modifier.height(8.dp)) if (reviews.isEmpty()) { Box( modifier = Modifier .fillMaxWidth() .padding(vertical = 32.dp), contentAlignment = Alignment.Center ) { Text( text = "No written reviews yet. Be the first to review this dish!", fontSize = 14.sp, color = TextSecondary ) } } else { LazyColumn( modifier = Modifier .fillMaxWidth() .height(350.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { items(reviews) { review -> ReviewItemCard(review = review) } } } Spacer(modifier = Modifier.height(20.dp)) } } } @Composable fun ReviewItemCard(review: FoodReview) { val dateStr = remember(review.timestamp) { val formatter = SimpleDateFormat("dd MMM yyyy, hh:mm a", Locale.getDefault()) formatter.format(Date(review.timestamp)) } Card( shape = RoundedCornerShape(12.dp), colors = CardDefaults.cardColors(containerColor = Color(0xFFF8F9FA)), elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), modifier = Modifier.fillMaxWidth() ) { Column( modifier = Modifier .fillMaxWidth() .padding(14.dp) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier .size(36.dp) .clip(CircleShape) .background(LoveRedPrimary.copy(alpha = 0.12f)), contentAlignment = Alignment.Center ) { Text( text = review.customerName.take(1).uppercase(), color = LoveRedPrimary, fontWeight = FontWeight.Bold, fontSize = 16.sp ) } Spacer(modifier = Modifier.width(10.dp)) Column { Text( text = review.customerName, fontWeight = FontWeight.Bold, fontSize = 14.sp, color = LoveBlack ) Text( text = dateStr, fontSize = 11.sp, color = TextSecondary ) } } Surface( shape = RoundedCornerShape(6.dp), color = AccentGold ) { Row( modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp), verticalAlignment = Alignment.CenterVertically ) { Icon( imageVector = Icons.Default.Star, contentDescription = null, tint = Color.White, modifier = Modifier.size(14.dp) ) Spacer(modifier = Modifier.width(4.dp)) Text( text = String.format(Locale.getDefault(), "%.1f", review.rating), color = Color.White, fontWeight = FontWeight.Bold, fontSize = 13.sp ) } } } if (review.reviewText.isNotBlank()) { Spacer(modifier = Modifier.height(10.dp)) Text( text = "\"${review.reviewText}\"", fontSize = 14.sp, color = LoveBlack, fontWeight = FontWeight.Medium, lineHeight = 18.sp ) } } } } @Composable fun WriteReviewDialog( foodItem: FoodItem, onDismiss: () -> Unit, onSubmit: (rating: Float, reviewText: String) -> Unit ) { var ratingState by remember { mutableFloatStateOf(5.0f) } var reviewTextInput by remember { mutableStateOf("") } var errorText by remember { mutableStateOf(null) } Dialog(onDismissRequest = onDismiss) { Surface( shape = RoundedCornerShape(20.dp), color = Color.White, shadowElevation = 8.dp, modifier = Modifier .fillMaxWidth() .padding(16.dp) ) { Column( modifier = Modifier .fillMaxWidth() .padding(20.dp) ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Rate & Review Dish", fontSize = 18.sp, fontWeight = FontWeight.Bold, color = LoveBlack ) IconButton(onClick = onDismiss) { Icon(imageVector = Icons.Default.Close, contentDescription = "Close", tint = TextSecondary) } } Spacer(modifier = Modifier.height(8.dp)) Text( text = foodItem.name, fontSize = 15.sp, fontWeight = FontWeight.SemiBold, color = LoveRedPrimary ) Spacer(modifier = Modifier.height(16.dp)) Text( text = "Select Star Rating:", fontSize = 13.sp, fontWeight = FontWeight.Medium, color = TextSecondary ) Spacer(modifier = Modifier.height(8.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { (1..5).forEach { star -> val isSelected = star <= ratingState.toInt() Icon( imageVector = if (isSelected) Icons.Default.Star else Icons.Outlined.Star, contentDescription = "$star Stars", tint = if (isSelected) AccentGold else Color.Gray, modifier = Modifier .size(36.dp) .clickable { ratingState = star.toFloat() } .padding(4.dp) ) } } Spacer(modifier = Modifier.height(16.dp)) Text( text = "Write your detailed review (\"Kya likh kar rating kar rahe hain\"):", fontSize = 13.sp, fontWeight = FontWeight.Medium, color = TextSecondary ) Spacer(modifier = Modifier.height(8.dp)) // Black text input field so user text is clearly visible as requested! OutlinedTextField( value = reviewTextInput, onValueChange = { reviewTextInput = it if (it.isNotBlank()) errorText = null }, placeholder = { Text("e.g. Dish was very fresh, spicy, delicious and hot!") }, colors = OutlinedTextFieldDefaults.colors( focusedTextColor = Color.Black, unfocusedTextColor = Color.Black, focusedBorderColor = LoveRedPrimary, unfocusedBorderColor = Color.LightGray, focusedContainerColor = Color(0xFFFAFAFA), unfocusedContainerColor = Color(0xFFFAFAFA) ), modifier = Modifier .fillMaxWidth() .height(110.dp) .testTag("review_text_input"), shape = RoundedCornerShape(12.dp), maxLines = 4 ) if (errorText != null) { Spacer(modifier = Modifier.height(4.dp)) Text( text = errorText!!, color = Color.Red, fontSize = 12.sp ) } Spacer(modifier = Modifier.height(20.dp)) Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End ) { Button( onClick = onDismiss, colors = ButtonDefaults.buttonColors(containerColor = Color.LightGray), shape = RoundedCornerShape(10.dp) ) { Text("Cancel", color = LoveBlack) } Spacer(modifier = Modifier.width(12.dp)) Button( onClick = { if (reviewTextInput.isBlank()) { errorText = "Please write a brief comment" } else { onSubmit(ratingState, reviewTextInput) } }, colors = ButtonDefaults.buttonColors(containerColor = LoveRedPrimary), shape = RoundedCornerShape(10.dp), modifier = Modifier.testTag("submit_review_button") ) { Text("Submit Review", color = Color.White, fontWeight = FontWeight.Bold) } } } } } }