From 4a2db6e30b42a95ea2416e40c8246f63f95ed64c Mon Sep 17 00:00:00 2001 From: Jucelio Coelho Date: Mon, 23 Sep 2024 17:04:14 -0300 Subject: [PATCH] ProductDetailsScreen OK --- .../data/OrderData.kt | 11 ++ .../data/ProductNutritionData.kt | 44 ++++++ .../data/ProductPreviewData.kt | 28 ++++ .../ui/screen/components/ProductHighlights.kt | 92 +++++++++++ .../components/ProductNutritionSection.kt | 108 +++++++++++++ .../components/ProductPreviewSection.kt | 145 ++++++++++++++++++ 6 files changed, 428 insertions(+) create mode 100644 app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/OrderData.kt create mode 100644 app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductNutritionData.kt create mode 100644 app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductPreviewData.kt create mode 100644 app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductHighlights.kt create mode 100644 app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductNutritionSection.kt create mode 100644 app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductPreviewSection.kt diff --git a/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/OrderData.kt b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/OrderData.kt new file mode 100644 index 0000000..78a8672 --- /dev/null +++ b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/OrderData.kt @@ -0,0 +1,11 @@ +package com.juceliodev.fooddeliverymyapplication.data + +data class OrderState( + val amount: Int, + val totalPrice: String +) + +val OrderData = OrderState( + amount = 5, + totalPrice = "$27.45" +) \ No newline at end of file diff --git a/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductNutritionData.kt b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductNutritionData.kt new file mode 100644 index 0000000..c806ba0 --- /dev/null +++ b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductNutritionData.kt @@ -0,0 +1,44 @@ +package com.juceliodev.fooddeliverymyapplication.data + +data class ProductNutritionState( + val calories: Calories, + val nutrition: List +) + +data class Calories( + val value: String, + val unit: String +) + +data class NutritionState( + val amount: String, + val unit: String, + val title: String +) + +val ProductNutritionData = ProductNutritionState( + calories = Calories( + value = "650", + unit = "Cal" + ), + nutrition = listOf( + NutritionState( + amount = "35", + unit = "g", + title = "Total Fat (45% DV)" + ), + NutritionState( + amount = "43", + unit = "g", + title = "Total Carbs (16% DV)" + ), + NutritionState( + amount = "36", + unit = "g", + title = "Protein" + ) + ) +) + + + diff --git a/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductPreviewData.kt b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductPreviewData.kt new file mode 100644 index 0000000..557846d --- /dev/null +++ b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/data/ProductPreviewData.kt @@ -0,0 +1,28 @@ +package com.juceliodev.fooddeliverymyapplication.data + +import androidx.annotation.DrawableRes +import com.juceliodev.fooddeliverymyapplication.R + +data class ProductHighlightState( + val text: String, + val type: ProductHighlightType +) + +enum class ProductHighlightType { + PRIMARY, SECONDARY +} + +data class ProductPreviewState( + val headline: String = "Mr. Cheezy", + @DrawableRes val productImg: Int = R.drawable.img_burger, + val highlights: List = listOf( + ProductHighlightState( + text = "Classic Taste", + type = ProductHighlightType.SECONDARY + ), + ProductHighlightState( + text = "Bestseller", + type = ProductHighlightType.PRIMARY + ) + ) +) \ No newline at end of file diff --git a/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductHighlights.kt b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductHighlights.kt new file mode 100644 index 0000000..5445e54 --- /dev/null +++ b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductHighlights.kt @@ -0,0 +1,92 @@ +package com.juceliodev.fooddeliverymyapplication.ui.screen.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +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.unit.dp +import com.juceliodev.fooddeliverymyapplication.data.ProductHighlightState +import com.juceliodev.fooddeliverymyapplication.data.ProductHighlightType +import com.juceliodev.fooddeliverymyapplication.ui.theme.AppTheme + + +@Composable +fun ProductHighlights( + modifier: Modifier = Modifier, + highlights: List +) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + highlights.onEach { item -> + Highlight( + text = item.text, + colors = HighlightDefaults.colors(item.type) + ) + } + } +} + +@Composable +private fun Highlight( + modifier: Modifier = Modifier, + text: String, + colors: HighlightColors = HighlightDefaults.defaultColors +) { + Surface( + modifier = modifier, + shape = RoundedCornerShape(percent = 50), + color = colors.containerColor, + contentColor = colors.contentColor + ) { + Box( + modifier = Modifier.padding( + vertical = 10.dp, + horizontal = 12.dp + ) + ) { + Text( + text = text, + style = AppTheme.typography.titleSmall.copy(fontWeight = FontWeight.Bold) + ) + } + } +} + +private object HighlightDefaults { + + val defaultColors = HighlightColors( + containerColor = Color.Unspecified, + contentColor = Color.Unspecified + ) + + @Composable + fun colors(type: ProductHighlightType): HighlightColors = when (type) { + ProductHighlightType.SECONDARY -> HighlightColors( + containerColor = AppTheme.colors.actionSurface, + contentColor = AppTheme.colors.onActionSurface + ) + + ProductHighlightType.PRIMARY -> HighlightColors( + containerColor = AppTheme.colors.highlightSurface, + contentColor = AppTheme.colors.onHighlightSurface + ) + } +} + +@Immutable +private data class HighlightColors( + val containerColor: Color, + val contentColor: Color +) \ No newline at end of file diff --git a/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductNutritionSection.kt b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductNutritionSection.kt new file mode 100644 index 0000000..697de5f --- /dev/null +++ b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductNutritionSection.kt @@ -0,0 +1,108 @@ +package com.juceliodev.fooddeliverymyapplication.ui.screen.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.juceliodev.fooddeliverymyapplication.data.Calories +import com.juceliodev.fooddeliverymyapplication.data.NutritionState +import com.juceliodev.fooddeliverymyapplication.data.ProductNutritionState +import com.juceliodev.fooddeliverymyapplication.ui.theme.AppTheme + + +@Composable +fun ProductNutritionSection( + modifier: Modifier = Modifier, + state: ProductNutritionState +) { + Column( + modifier = modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + SectionHeader( + title = "Nutrition facts", + calories = state.calories + ) + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + state.nutrition.onEach { item -> NutritionItem(state = item) } + } + } +} + +@Composable +private fun SectionHeader( + modifier: Modifier = Modifier, + title: String, + calories: Calories +) { + Row( + modifier = modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = title, + style = AppTheme.typography.titleLarge, + color = AppTheme.colors.onBackground + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = calories.value, + style = AppTheme.typography.titleMedium, + color = AppTheme.colors.onBackground + ) + Text( + text = calories.unit, + style = AppTheme.typography.titleMedium, + color = AppTheme.colors.onBackground + ) + } + } +} + +@Composable +private fun NutritionItem( + modifier: Modifier = Modifier, + state: NutritionState +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(2.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = state.amount, + style = AppTheme.typography.titleMedium, + fontWeight = FontWeight.Light, + color = AppTheme.colors.onBackground + ) + Text( + text = state.unit, + style = AppTheme.typography.titleMedium, + color = AppTheme.colors.onBackground, + fontWeight = FontWeight.Light + ) + } + Text( + text = state.title, + style = AppTheme.typography.label, + color = AppTheme.colors.onBackground + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductPreviewSection.kt b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductPreviewSection.kt new file mode 100644 index 0000000..e43b811 --- /dev/null +++ b/app/src/main/java/com/juceliodev/fooddeliverymyapplication/ui/screen/components/ProductPreviewSection.kt @@ -0,0 +1,145 @@ +package com.juceliodev.fooddeliverymyapplication.ui.screen.components + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +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.statusBarsPadding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import com.juceliodev.fooddeliverymyapplication.R +import com.juceliodev.fooddeliverymyapplication.data.ProductPreviewState +import com.juceliodev.fooddeliverymyapplication.ui.theme.AppTheme + +@Composable +fun ProductPreviewSection( + modifier: Modifier = Modifier, + state: ProductPreviewState +) { + Box( + modifier = modifier.height(IntrinsicSize.Max) + ) { + ProductBackground( + Modifier.padding(bottom = 24.dp) + ) + Content( + state = state, + modifier = Modifier + .statusBarsPadding() + .padding(top = 24.dp) + ) + } +} + +@Composable +private fun ProductBackground( + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxSize() + .background( + color = AppTheme.colors.secondarySurface, + shape = RoundedCornerShape(bottomStart = 32.dp, bottomEnd = 32.dp) + ) + ) +} + +@Composable +private fun Content( + modifier: Modifier = Modifier, + state: ProductPreviewState +) { + ConstraintLayout( + modifier = modifier.fillMaxWidth() + ) { + val (actionBar, highlights, productImg) = createRefs() + + ActionBar( + headline = state.headline, + modifier = Modifier + .padding(horizontal = 19.dp) + .constrainAs(actionBar) { + top.linkTo(parent.top) + } + ) + + Image( + painter = painterResource(id = state.productImg), + contentDescription = null, + contentScale = ContentScale.FillHeight, + modifier = Modifier + .height(256.dp) + .constrainAs(productImg) { + end.linkTo(parent.end) + top.linkTo(anchor = actionBar.bottom, margin = 20.dp) + } + ) + + ProductHighlights( + highlights = state.highlights, + modifier = Modifier.constrainAs(highlights) { + start.linkTo(anchor = parent.start, margin = 19.dp) + top.linkTo(productImg.top) + } + ) + } +} + +@Composable +private fun ActionBar( + modifier: Modifier = Modifier, + headline: String +) { + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = headline, + style = AppTheme.typography.headline, + color = AppTheme.colors.onSecondarySurface + ) + CloseButton() + } +} + +@Composable +private fun CloseButton( + modifier: Modifier = Modifier +) { + Surface( + modifier = modifier.size(44.dp), + shape = RoundedCornerShape(16.dp), + color = AppTheme.colors.actionSurface, + contentColor = AppTheme.colors.secondarySurface + ) { + Box( + modifier = modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Icon( + painter = painterResource(id = R.drawable.ic_close), + contentDescription = null, + modifier = Modifier.size(24.dp) + ) + } + } +}